Spring系列之注解配置

Spring是轻代码而重配置的框架,配置比较繁重,影响开发效率,所以注解开发是一种趋势,注解代替xml配置文件可以简化配置,提高开发效率

你本来要写一段很长的代码来构造一个Beam对象,但是如果使用注解的话只要使用一个注解符号即可

下面我们来讲讲一些经常使用的注解符号

@Component 使用类上用于实例化Bean

@Controller 使用web层类上用于实例化Bean

@Service 使用在Service层类上用于实例化service

@Repository 使用在dao层类上用于实例化Bean

@Autorwired 使用在字段上用于根据类型依赖注入

@Qualifier 结合结合@Autowired一起使用根据名称进行依赖注入

@Resource 相当于@Autowired+@Qualifier一起使用

@Scope 标注bean的范围

@PostConstruct 使用该在方法上标注该方法是Bean的初始化方法

@PostDestory 使用在方法上标注该方法是Bean的销毁方法

这三个没有什么区别,不过是为了在后期读代码的时候更加利于我们区分,比如看到@Controller就知道这是web层,看到@Service就知道这是service层

@Component  使用类上用于实例化Bean
@Controller 使用web层类上用于实例化Bean
@Service 使用在Service层类上用于实例化service
@Repository 使用在dao层类上用于实例化Bean

所以我们只需讲一个即可,其他的使用方法均相同,这里我们使用@Component来讲解

定义一个userDaolmp类

package com.pjh.dao;
import com.pjh.dao.Imp.userdao;
import org.springframework.stereotype.Component;
@Component("userDaoImp")
public class userDaoImp implements userdao {
public void save() {
System.out.println("save");
}
}

定义一个测试类测试

@Test
public void test(){
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
userdao userDaoImp =(userdao) classPathXmlApplicationContext.getBean("userDaoImp");
userDaoImp.save();
}

然后我们就发现了如下报错

由蓝色的划线部分我们可以看出问题是:没有一个名叫userDaoImp的bean



这是为什呢?因为我们虽然写了注解,但是我们要让applicationContext.xml知道我们使用了注解,要告诉他哪里有个bean。所以我们在applicationContext中还需要加入以下配置

命名空间:xmlns:context="http://www.springframework.org/schema/context

约束路径http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd

注解的组件扫描:

<context:component-scan base-package="com.pjh"/>

成功运行

接下来我们再来讲讲如何使用注解进行注入

方式一:使用@Autowired+@Qualifier

目的:创建一个userdao类将其注入带service类中

userdao类代码

package com.pjh.dao;
import com.pjh.dao.Imp.userdao;
import org.springframework.stereotype.Component;
@Component("userDaoImp")
public class userDaoImp implements userdao {
public void save() {
System.out.println("save");
}
}

service类代码

package com.pjh.service.Imp;
import com.pjh.dao.Imp.userdao;
import com.pjh.dao.userDaoImp;
import com.pjh.service.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;
import javax.annotation.Resource;
import javax.xml.bind.SchemaOutputResolver; @Repository("serviceImp")
public class serviceImp implements service {
@Autowired
@Qualifier("userDaoImp") private userDaoImp userDaoImp;
public void save() {
System.out.println("sssssss");
userDaoImp.save();
} }

测试类

@Test
public void test(){
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
service service =(service) classPathXmlApplicationContext.getBean("serviceImp");
service.save();
}

结果

方式二:使用@Resource()

就是把 @Autowired + @Qualifier("userDaoImp")换成@Resource(name="userDaoImp"),其余代码均与方式一相同

package com.pjh.service.Imp;
import com.pjh.dao.Imp.userdao;
import com.pjh.dao.userDaoImp;
import com.pjh.service.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;
import javax.annotation.Resource;
import javax.xml.bind.SchemaOutputResolver;
@Repository("serviceImp")
public class serviceImp implements service {
/* @Autowired
@Qualifier("userDaoImp")*/
@Resource(name="userDaoImp")
private userDaoImp userDaoImp;
public void save() {
System.out.println("sssssss");
userDaoImp.save();
} }

结果



令人蛋碎的事情来了,报错了,意思是不支持版本5



解决方案:

File->setting下设置项目的jdk版本

File->ProjectStruct下设置版本



结果



又报错了,这。。。。。我tm心态崩了呀

根据报错的内容是报了个空指针异常,这是为什么呢?为什么使用@Autowired + @Qualifier("userDaoImp")不报错换成@Resource(name="userDaoImp")就报空指针呢

原因:jdk版本不支持

解决方案:

1.更换本地的jdk版本,最好jdk1.8以上,jdk9不支持有bug

2.再maven.pom文件中引入如下依赖

<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-annotations-api</artifactId>
<version>7.0.47</version>
</dependency>

结果

成功运行

终于解决完了



使用@Scope注解标注Bean的范围

使用@Scope("prototype")

package com.pjh.dao;
import com.pjh.dao.Imp.userdao;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component("userDaoImp")
@Scope("prototype")
public class userDaoImp implements userdao {
public void save() {
System.out.println("save");
}
}

测试代码

@Test
public void test(){
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
userdao userdao =(userdao) classPathXmlApplicationContext.getBean("userDaoImp");
userdao userdao1 =(userdao) classPathXmlApplicationContext.getBean("userDaoImp");
System.out.println(userdao);
System.out.println(userdao1);
}

结果

使用@Scope("singleton")

package com.pjh.dao;
import com.pjh.dao.Imp.userdao;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component("userDaoImp")
@Scope("singleton")
public class userDaoImp implements userdao {
public void save() {
System.out.println("save");
}
}

结果



在这里顺便给大家复习复习singleton与prototype的区别吧

singleton

Bean的实例化个数:1个

Bean的实例化时机:当Spring核心配置文件被加载时

Bean的生命周期:

对象创建:当应用加载时对象创建

对象运行:只要容器在,对象就一直活着

对象销毁:当应用卸载,容器销毁时

prototype:在使用getBean方法的时候创建bean

prototype

Bean的实例化格式:多个

Bean的实例化时机:当调用getBean()方法时,实例化Bean

对象创建:当使用对象时,创建新的对象实例

对象运行:只要对象在使用中,对象就一直存在

对象销毁:对象长时间不使用,就会被java的垃圾回收机制回收

初始化方法和销毁方法

初始化方法

@PostConstract

@PostConstruct
public void constract(){
System.out.println("初始化方法");
}

销毁方法

@PostDestroy

 @PreDestroy
public void destroy(){
System.out.println("在对象销毁前执行");
}

@Value()进行注入

package com.pjh.dao;
import com.pjh.dao.Imp.userdao;
import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Component("userDaoImp")
@Scope("singleton")
public class userDaoImp implements userdao {
public void save() {
System.out.println("save");
System.out.println("读取配置文件:"+one);
System.out.println("普通类型:"+a);
}
@Value("${one.one}")
private String one;
@Value("4")
private String a; }

配置文件信息

one.one=1

applicationContext中添加的内容

 <context:property-placeholder location="classpath*:one.properties"/>

测试代码

@Test
public void test(){
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
userdao userdao =(userdao) classPathXmlApplicationContext.getBean("userDaoImp");
userdao.save();
}

结果



使用上面的注解还不可以全部替代xml配置文件,还需要使用注解替代的配置如下

非自定义的Bean的配置:

加载properties文件的配置:<context:property-placeholder>

注解扫描的配置:context:component-scan

引入其他文件:

Spring新注解

@Configuration 用于指定当前类是一个Spring配置类,创建容器时会从该类上加载注解,该类不能是匿名类与final类

@ComponentScan 用于指定Spring在初始化容器的时候要扫描包

作用与Spring中的此代码相同:context:component-scan

@Bean 使用方法,将该方法的返回值返回到容器中

@Import 用于导入其他配置类

@PropertySource 用于加载properties文件中的配置

案例

核心配置类

package com.pjh.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Component;
/*标志该类是核心配置类*/
@Configuration
/*扫描包*/
@Component("com/pjh")
/*导入其他配置类*/
@Import(DataSourceConfig.class)
public class Springconfig {
}

副配置类

package com.pjh.config;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;
/*加载配置文件*/
@PropertySource("classpath:jdbc.properties")
public class DataSourceConfig {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
/*Spring会将当前方法的返回值以指定名称存储到Spring容器中*/
@Bean("dataSource")
public DataSource getDataSource() throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass(driver);
dataSource.setJdbcUrl(url);
dataSource.setUser(username);
dataSource.setPassword(password);
return dataSource;
}
}

测试函数

@Test
public void test() throws SQLException {
ApplicationContext applicationContext = new
AnnotationConfigApplicationContext(Springconfig.class);
DataSource bean = (DataSource)applicationContext.getBean("dataSource");
Connection connection = bean.getConnection();
System.out.println(connection);
}

结果

成功创建connection连接

Spring集成junit

为什么使用Spring集成junit?

在测试类中每个类都要写下面的两行代码

ApplicationContext applicationContext = new
AnnotationConfigApplicationContext(Springconfig.class);
DataSource bean = (DataSource)applicationContext.getBean("dataSource");

这两行代码的作用是获取容器,不写的话报空指针异常

为了让我们测试的时候不用进行反复的写上述两行的操作,我们使用Spring来集成junit,用springjunit来创建spring容器,

我们只需将配置文件的名称告诉他们即可,将需要的bean直接在容器中进行注入

Spring集成junit的步骤

需要导入的jar包

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>

这是我spring系列的学习文章,我也会不断的学习,文章如有错误还请批评指正,如有帮助大家可以点点关注,我们一同学习

Spring系列之新注解配置+Spring集成junit+注解注入的更多相关文章

  1. JAVAEE——spring02:使用注解配置spring、sts插件、junit整合测试和aop演示

    一.使用注解配置spring 1.步骤 1.1 导包4+2+spring-aop 1.2 为主配置文件引入新的命名空间(约束) 1.3 开启使用注解代替配置文件 1.4 在类中使用注解完成配置 2.将 ...

  2. 使用注解配置Spring

    使用注解配置Spring 1.为主配置文件引入新的命名空间(约束) 2.开启使用注解代理配置文件 3.在类中使用注解完成配置 将对象注册到容器 修改对象的作用范围 值类型注入 引用类型注入 注意: 初 ...

  3. 注解配置spring

    1.为什么使用注解配置Spring基于注解配置的方式也已经逐渐代替xml.这个是不可逆的潮流,所以我们必须要掌握使用注解的方式配置Spring 总结:(1)使用注解配置Spring,注解的作用就是用于 ...

  4. Spring中添加新的配置表,并对新的配置表进行处理

    实习过程中boss交代的任务(以下出现的代码以及数据只给出小部分,提供一个思路) 目的:Spring中添加新的配置表,并对新的配置表进行处理:替换的新的配置表要友好,同时保证替换前后功能不能发生变化. ...

  5. Spring系列 之数据源的配置 数据库 数据源 连接池的区别

    Spring系列之数据源的配置 数据源,连接池,数据库三者的区别 连接池:这个应该都学习过,比如c3p0,druid等等,连接池的作用是为了提高程序的效率,因为频繁的去创建,关闭数据库连接,会对性能有 ...

  6. Spring系列(六):Spring事务源码解析

    一.事务概述 1.1 什么是事务 事务是一组原子性的SQL查询,或者说是一个独立的工作单元.要么全部执行,要么全部不执行. 1.2 事务的特性(ACID) ①原子性(atomicity) 一个事务必须 ...

  7. Spring系列(二):Spring IoC应用

    一.Spring IoC的核心概念 IoC(Inversion of Control  控制反转),详细的概念见Spring系列(一):Spring核心概念 二.Spring IoC的应用 1.定义B ...

  8. Spring系列(三):Spring IoC源码解析

    一.Spring容器类继承图 二.容器前期准备 IoC源码解析入口: /** * @desc: ioc原理解析 启动 * @author: toby * @date: 2019/7/22 22:20 ...

  9. 朱晔和你聊Spring系列S1E11:小测Spring Cloud Kubernetes @ 阿里云K8S

    有关Spring Cloud Kubernates(以下简称SCK)详见https://github.com/spring-cloud/spring-cloud-kubernetes,在本文中我们主要 ...

随机推荐

  1. 深入理解k8s中的访问控制(认证、鉴权、审计)流程

    Kubernetes自身并没有用户管理能力,无法像操作Pod一样,通过API的方式创建/删除一个用户实例,也无法在etcd中找到用户对应的存储对象. 在Kubernetes的访问控制流程中,用户模型是 ...

  2. 团队作业4:第七篇Scrum冲刺博客(歪瑞古德小队)

    目录 一.Daily Scrum Meeting 1.1 会议照片 1.2 项目进展 二.项目燃尽图 三.签入记录 3.1 代码/文档签入记录 3.2 Code Review 记录 3.3 issue ...

  3. 喵的Unity游戏开发之路 - 在球体上行走

    很多童鞋没有系统的Unity3D游戏开发基础,也不知道从何开始学.为此我们精选了一套国外优秀的Unity3D游戏开发教程,翻译整理后放送给大家,教您从零开始一步一步掌握Unity3D游戏开发. 本文不 ...

  4. Dockerfile文件万字全面解析

    阅读目录 目录 阅读目录 用法 格式 Parser directives escape 环境替换 .dockerignore file FROM RUN CMD LABEL MAINTAINER EX ...

  5. Java面试题(异常篇)

    异常 74.throw 和 throws 的区别? throws是用来声明一个方法可能抛出的所有异常信息,throws是将异常声明但是不处理,而是将异常往上传,谁调用我就交给谁处理.而throw则是指 ...

  6. 数据处理 | pandas入门专题——离散化与one-hot

    今天是pandas数据处理专题第7篇文章,可以点击上方专辑查看往期文章. 在上一篇文章当中我们介绍了对dataframe进行排序以及计算排名的一些方法,在今天的文章当中我们来了解一下dataframe ...

  7. ZERO:点击影响的量化 & 分清SEO的不可抗力

    http://www.wocaoseo.com/thread-331-1-1.html 这篇文章基于上篇(http://www.wocaoseo.com/thread-332-1-1.html)的理论 ...

  8. SICP之应用序和正则序

    以一个题目来说明 (define (square x) (* x x)) (define (sum-squares x y) (+ (square x) (square y))) (define (f ...

  9. go语言之反射

    ---恢复内容开始--- 一 :并发基础 1 并发和并行 并发和并行是两个不同的概念: 并行意味着程序在任意时刻都是同时运行的: 并发意味着程序在单位时间内是同时运行的 详解: 并行就是在任一粒度的时 ...

  10. JS - 有趣的面试题

    for (var i = 0; i < 5; i++) { setTimeout(function() { console.log(i); }, 1000); } //这个例子执行完输出什么结果 ...