Spring IoC容器(XML&注解配置+Java代码配置+整合Junit4+Junit5)

Spring IoC容器(XML&注解配置+Java代码配置+整合Junit4+Junit5)

  • 一、Spring支持的注解类型
  • 二、Spring注解开启方式
    • 2.0 准备工作【必须】
    • 2.1 < context:annotation-config >标签
    • 2.2 < context:component-scan >标签
    • 2.3 Spring支持的Java标准注解
      • @Named----组件注解
      • @Resource----依赖注入注解
      • @Inject----依赖注入注解
    • 2.4 Spring容器配置注解
      • @Required----依赖项检查
      • @Autowired----依赖对象的自动装配
      • @Compronent----组件注解
      • @Bean----方法层级的组件注解
      • @Scope----组件作用域注解
      • @Description----描述组件的注解
      • @Lazy----组件懒加载注解
      • @Value----基本类型注入的注解
      • @PropertySource----指定资源文件位置的注解
    • 2.5 自动装配的顺序和选择
      • @Primary----依赖的主候选
      • @Qualifier----精确查找依赖
      • @Order----同类型的集合注入顺序
  • 三、基于Java代码的配置
    • @Configuration----配置类注解
    • 容器初始化----Java代码配置
    • @ComponentScan----组件扫描注解
    • @Import----配置类导入注解
  • 四、Spring整合Junit
    • 4.1 添加依赖
    • 4.2 @RunWith注解替换原有运行器
    • 4.3 @ContextConfiguration读取配置文件或注解
    • 4.4 @Autowired注入数据
    • 4.5 【拓展】Spring 整合 Junit5

参考/摘录书籍:Spring+Spring MVC+MyBatis整合开发 著○陈学明
参考图片:来自网络/自己提供
说明:本人相关博客仅供学习参考!

一、Spring支持的注解类型

  默认情况下,注解功能是关闭的,通过简单配置即可开启类的注解功能。
  从功能角度来看,注解可分为组件注解依赖注解

类别 注解 归属 功能
组件 @Named Java标准 组件注册
@Component Spring 组件注册(类)
@Bean Spring 组件注册(方法)
@Scope Spring 组件作用域
@PostConstruct Java标准 组件初始化方法回调
@PreDestroy Java标准 组件销毁方法回调
依赖注入 @Resource Java标准 依赖注入
@Inject Java标准 依赖注入
@Required Spring 依赖检查
@Autowired Spring 依赖自动装配
@Nullable Java标准或Spring 非空检查
@Primary Spring 依赖注入Bean优先级,结合@Component和@Bean使用
@Qualifier Spring 依赖依赖注入限定字符,结合@Autowired使用
@Order Spring 组件注入顺序,结合@Component和@Bean使用
配置 @Configuration Spring 配置类注解
@ComponentScan Spring 组件扫描注解
@Import Spring 导入其它配置类

二、Spring注解开启方式

  Spring提供或实现的容器配置注解,在默认情况加使用并不会立即生效,需要配置相关的处理类进行处理。
  Spring提供了3种方式开启此类型注解功能。【列举常用2种】

2.0 准备工作【必须】

  在使用context标签时,需要在根元素中添加context的命名空间和命名空间相应的XML结构定义文档的位置,两者是成对配置的。


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
	       http://www.springframework.org/schema/beans
	       http://www.springframework.org/schema/beans/spring-beans.xsd
	       http://www.springframework.org/schema/context
	       http://www.springframework.org/schema/context/spring-context.xsd">
	
beans>

2.1 < context:annotation-config >标签

  在配置文件 beanx.xml 中加入一行代码,开启4种注解的支持:
【该注解不会开启@Component等组件的注解功能】


<context:annotation-config />

该标签的实质是一次性在容器中注册以下4种PostProcessor的Bean:
1、CommonAnnotationBeanPostProcessor:Java公共注解(@Resource注解)
2、AutowiredAnnotationBeanPostProcessor:自动装配注解(@Autowired注解)
3、RequiredAnnotationBeanPostProcessor:非空检查注解(@Required注解)
4、PersistenceAnnotationBeanPostProcessor:持久化注解(@Persistence注解)

2.2 < context:component-scan >标签

  上面的开启方式不会开启@Component等组件的注解功能。要开启此类型注解,需要进行路径扫描的配置:【推荐使用】


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

【注意】如果配置了component-scan,就不需要配置annotation-config的配置了!
【扩展】

  1. component-scan也可以通过设置属性annotation-config=“false”来禁用@Autowired、@Required、@Resource等注解功能,而仅处理@Component等组件注解。

2.3 Spring支持的Java标准注解

@Named----组件注解

  @Named使用在属性参数上,作用是根据名字查找容器中对应的对象;
  也可以使用在上,用于对该类进行组件的标注,功能类似于在XML文件中配置Bean。

@Named("myCustomBean")		//定义该类的实例在容器中的名字
public class MyCustomBean{
}

与XML配置一样,如果不指定Bean的名字,默认以首字母小写的类名作为Bean的名字。

@Resource----依赖注入注解

  该注解是Java自带的注解。Spring支持这个注解来引用被Spring容器管理的对象,包括自定义的Bean实例和容器对象。
  @Resource注解的属性或Setter方法,默认会以属性名或者Setter方法参数名去查找容器中的对象,如果没有找到,则使用类来查找。也可以显式地使用属性name来查找指定名称的Bean实例:

@Resource有两个属性是比较重要的,分别是name和type;Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。默认按name进行注入

情景1:【应用在属性上】
@Resource(name="book")		//通过名字来查找容器中对应的对象
private com.ccbx.pojo.Book book;

情景2:【应用在Setter方法上】
/**
 * 首先会从容器中查找名为book的Bean;如果没找到,则使用类来查找和注入;
 */
@Resource
public void setBook(Book book){
	this.book = book;
}

注意:

//如果接收的对象是接口,注入的是接口的实现类,此时要注意写接口实现类的名称(默认首字母小写)
//否则在容器中查找不到指定名称的bean组件
@Resource(name = "userLoginRecordServiceImpl")
private UserLoginRecordService ulrs;

@Inject----依赖注入注解

  @Inject可以使用在构造函数、属性、属性的Setter方法上,用来注入依赖对象:

@Inject		//1.构造函数注入依赖对象
public Book(Foo foo){
	this.foo = foo;
}

@Ijnect		//2.属性注入依赖对象
private User user;

@Ijnect		//3.属性Setter方法注入依赖对象
public void setUser(User user){
	this.user = user;
}

@Ijnect		//【拓展】结合 @Named注解,注入指定名字的依赖
public void setUser(@Named("userBean1") User user){
	this.user = user;
}

@Inject注解的属性、构造函数、方法,默认会以属性或参数名称查找容器中的对象。
【注意】如果注入的Bean没有找到,则容器在初始化时会抛出UnsatisfiedDependencyException异常提示。

2.4 Spring容器配置注解

@Required----依赖项检查

  @Required用于属性的Setter方法上,以检查该属性是否进行了依赖注入。
  以XML配置Bean和注入依赖的方式来说,就是检查该属性对应的是否被正确配置。@Required是对XML文件中的配置依赖项进行检查】

例子:

<bean id="user" class="com.ccbx.pojo.User" />
<bean id="bookBean" class="com.ccbx.pojo.Book" >
	<property name="user" ref="user" />
bean>
public class RequiredTest{
	//属性
	public User user;
	
	@Required		//对依赖对象是否有配置进行检查
	public void setUser(User user){
		this.user = user;
	}
}

【注意】

  1. 如果user属性注入user的配置被注释了(注释标签),则在容器启动时会抛出BeanInitializationException 异常提示!
  2. @Autowired默认是required的,也就是备注接的依赖对象必须已经在容器中注册。如果没有,则抛出UnsatisfiedDependencyException 异常,容器初始化失败。

@Autowired----依赖对象的自动装配

  @Autowired注解,直接在代码中进行依赖对象的自动装载。【依赖对象的注入】@Autowired会自动在容器中查找依赖项并注入】(该注解是根据Bean的类型来查找,有多个类型相同得对象时再根据名字来查找依赖对象。)
  @Autowired注解可以使用在 类构造器属性属性Setter方法一般方法 上。

@AutoWired是spring的注解,Autowired只根据type进行注入,不会去匹配name。如果涉及到type无法辨别注入对象时,那需要依赖 @Qualifier 或 @Primary 注解一起来修饰。

  1. 构造器中使用@Autowired
@Autowired
public BookDao(Book book){
	this.book = book;
}
  1. Setter方法一般方法中使用@Autowired
@Autowired		//在Setter方法中使用
public void setBook(Book book){
	this.book = book;
}

@Autowired		//在一般方法中使用
public void initUser(User user){
	this.user = user;
}

【注意】这里注解@Autowired的一般方法虽然没有被调用,容器也会将依赖对象注入,从而设置user属性的值。

  1. 属性中应用@Autowired

可以在任何作用域的属性中使用@Autowired注解。配置方式如下:

@Autowired
private User user;

//****************多个Bean对应同一个类的情况***************
@Autowired		//自动装载数组类型的依赖
private User[] user;
@Autowired		//自动装载集合类型的依赖
private Set<User> userSet;
@Autowired		//自动装载键值对类型的依赖
private Map<String,User> userMap;
//【注意】Map的键和值分别是Bean的id和根据Bean配置产生的实例!!!

在属性上配置该注解后,相应的只需要在配置文件中配置Bean的简单形式即可完成自动装配:

<bean id="user" class="com.ccbx.pojo.User" />
@Autowired(required="false")	//取消初始化时的依赖检查
public void setBook(Book book){
	this.book = book;
}

@Autowired	
public void setBook(@Nullable Book book){	//使用@Nullable检查非空【效果同上】
	this.book = book;
}

【注意】

  1. @Autowired默认根据类来查找和注入容器中管理的对象,对于注解的属性和参数依赖要确保响应的Bean被容器托管(对XML而言,要在其中定义相应的Bean),否则容器在初始化的时候就会找不到依赖对象而无法正常启动。
  2. 如果多个Bean对应一个类的话,则使用该类集合类型装载就可以得到该类的所有Bean的集合,集合类型包括该类的Array[]、Set、Map。(上方已给出)
  3. @Autowired默认是required的,也就是备注接的依赖对象必须已经在容器中注册。如果没有,则抛出UnsatisfiedDependencyException 异常,容器初始化失败。和@Required注解的效果一致(但有区别)。
  4. 如果程序在运行时才需要注入Bean,而不是在容器初始化时进行装配注入,这种情况下可以通过设置required=false的属性值,取消在容器初始化时对依赖对象的检查。也可以在方法参数上使用@Nullable 注解达到同样效果。【上面例子已列出】
  5. @Autowired可以用来自动装配自定义类的Bean,也可以用来装配容器的上下文和容器对象,包括BeanFactoryApplicationContextEnvironmentResourceLoaderApplicationEventPublisherMessageSource等。
  6. 显示依赖注入会覆盖自动装配。

@Compronent----组件注解

  通过@Autowired 注解将 依赖注入从XML配置转到Java代码中,更进一步,可以将Bean的定义也放到Java代码中使用注解的方式进行配置。
  在类中使用@Component 注解,容器可以在启动时进行该类的实例化。【该注解及其子注解是使用在类层级的组件注解】
  通过配置 标签即可开启@Component 注解功能,默认状况下会扫描 base-package 包下的所有 @Component 和 子注解(@Repository、@Service、@Controller)标注的类进行实例化并注册。

在该注解的基础上定义了不同层级的子注解,如下:
Spring IoC容器(XML&注解配置+Java代码配置+整合Junit4+Junit5)_第1张图片

@Bean----方法层级的组件注解

  @Bean 注解该注解只能写在方法上,表明使用此方法创建一个对象,并且放入 spring 容器。
@Bean注解的方法】需要有非空的返回类型,返回的对象就是注册Bean的对象。该注解只有在其方法对应的类被注册为Bean的情况加才有效(可以通过XML配置或@Component注解配置)【也就是所在类必须要被注册】
默认情况加,@Bean注解方法注册的Bean的id是方法名。可以用name属性指定名称,value属性指定别名。name和value可以单独使用,也可以一起使用,共同使用要保持name和value的值一致,否则会出错

// name属性 和 value属性 共同使用的时候要保证值一致
@Bean(name="userBean",value="userBean")

  容器在执行 @Bean 注解方法实例化Bean时,如果该方法有输入参数,则容器会根据参数名查找Bean并作为依赖项进行注入,没有找到,则容器启动失败。

@Component
public class User{
	@Bean		//默认注册的Bean的id为initTeacher;
	public Teacher initTeacher(Teacher teacher){	//该方法中的参数teacher会自动从Spring容器中查找注入,没有找到则注入失败
		return teacher;		//返回的对象就是注册Bean的对象
	}
}

【注意】@Bean注解的方法不能是private或final,注册Bean的id就是方法名。

@Scope----组件作用域注解

  @Bean注解默认注册的是singleton作用域的Bean实例,结合@Scope 注解可以定义其作用域范围,比如源性作用域定义@Scope("prototype")

@Description----描述组件的注解

  @Description注解可以对该Bean做一些详细的描述,注解的描述内容通过beanDefinition.getDescription()方式获取。

案例:
Spring IoC容器(XML&注解配置+Java代码配置+整合Junit4+Junit5)_第2张图片

@Lazy----组件懒加载注解

作用:设置bean的懒加载,相当于

@Value----基本类型注入的注解

作用:注入基本类型(包装类型)和String 类型数据。
注意:该注解所在的类必须是在 IoC 容器中!(即必须是一个容器中的Bean)

@Value("520")	//给基本类型的包装类型注入数据
private Integer num;
@Value("这是一个注入的字符串的值")	//给String类型注入数据
private String str;
  1. 修饰的属性不需要提供私有属性的set方法 。(内部自动去操作私有属性,通过反射给属性赋值)

@PropertySource----指定资源文件位置的注解

作用:用于加载.properties配置文件。
  例如我们配置数据源时,可以把连接数据库的信息写到properties 配置文件中,就可以使用此注解指定 properties 配置文件的位置。
Spring IoC容器(XML&注解配置+Java代码配置+整合Junit4+Junit5)_第3张图片

value 属性:用于指定 properties 文件位置。如果是在类路径下,需要加上 classpath:
【注意】

  1. 上面用了@Value(“${xxx}”),它是将properties文件中的value注入给类的成员变量,xxx就是key。
  2. properties配置文件中的key不要用username(用username得到的是系统的用户名),我们换个名称user或者用两级名称jdbc.username。

2.5 自动装配的顺序和选择

  在同一个类被注入多个Bean实例的情况下,使用@Autowired可以注入该类的依赖对象和该类对象的集合。
  @Autowired 默认根据类来查找和注入容器中的对象,如果存在同一个类的多个Bean实例被容器管理的情况,在使用 @Autowired 装配该类的依赖时会报错UnsatisfiedDependencyException 异常,容器初始化失败。解决方式如下:

  • 注入该类的对象时,需要在某一个Bean的配置上使用@Primary 注解标注该Bean实例优先被使用,也可以结合@Autowired和@Qualifier,通过名称等限定标识符查找某一个Bean实例。
  • 注入该类的对象时,在Bean配置中使用@Order 注解可以设定各Bean实例在集合中的顺序。

@Primary----依赖的主候选

  在XML的配置中使用primary 属性设置是否是主候选Bean,primary=ture表示优先使用。

<bean id="book1" class="com.java.entity.Book" primary="true"/>

  在使用Java注解进行组件和依赖配置的方式下,可以将@Primary 注解使用在类和方法上。【@Primary可以使用在@Component注解的类中,也可以使用在@Bean注解的方法上】

@Bean	//组件注解
@Primary	//如果User类对应的Bean在容器中有多个,其他Bean在使用user对象时会优先使用该注解修饰的Bean
public User secondUser(){
	return new User();
}

@Qualifier----精确查找依赖

  结合@Qualifier 和 @Autowired根据Bean的名字来查找依赖对象。
  找到多个同类型的依赖时,@Qualifier用来筛选候选者;@Qualifier可以使用在属性方法参数中。

//*************使用在属性上**************
@Autowired
@Qualifier("bookDao1")	//简写形式;告诉容器只注入id="bookDao1"的Bean实例
private BookDao bd;

@Order----同类型的集合注入顺序

  集合中的元素顺序默认是在XML文件中的配置顺序或以@Bean注解的顺序进行排序。@Order 注解可以指定Bean注入的顺序。

@Bean	//组件注解
@Order(1)	//该注册的实例在类实例集合中的顺序
public User createUser(){
	return new User("第一个创建的User的实例");
}
@Autowired	//自动装载时,集合中元素的顺序会根据@Order注解的值来排序
private List<User> userList;

【注意】@Order后面的数值越小,优先级越高,在集合中的位置就越靠前。

三、基于Java代码的配置

@Configuration----配置类注解

Spring IoC容器(XML&注解配置+Java代码配置+整合Junit4+Junit5)_第4张图片
  @Configuration也是一种组件类型的注解。
  使用 @Configuration 注解的类相当于XML配置的元素,该类中的方法使用 @Bean 注解注册组件,相当于XML配置中的元素。

@Configuration	//配置类注解
public class AppConfig{
	@Bean	//组件注解【默认注册的实例id=user即方法名】
	public User user(){
		return new User();
	}
}

以上效果等同于XML配置

<beans>		
	<bean class="com.ccbx.pojo.User" />
beans>

【注意】

  1. 在非@Configuration注解类的@Bean注解方法中不能定义Bean之间的依赖关系,如果定义在非@Configuration注解类的依赖关系中,则有可能被当做一般的方法被调用,而不是用来作为Bean定义的方法。

容器初始化----Java代码配置

  XML的容器的配置方式使用ClassPathXmlApplicationContextFileSystemXmlApplicationContextGenericXmlApplicationContext来读取配置文件并初始化容器,代码配置方式使用AnnotationConfigApplicationContext根据@Configuration注册的配置类来初始化容器。

//【方式1】:代码方式初始化容器:[多个配置类之间用逗号隔开]
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig1.class,AppConfig2.class);

//【方式2】:代码方式初始化容器:[配置类可以再上下文初始化之后通过方法register()进行注册,效果类似]
ApplicationContext context = new AnnotationConfigApplicationContext();
context.register(AppConfig.class);	//注册注解配置类
context.register(Book.class);		//注册注解类
context.refresh();					//更新容器

【注意】

  1. register( ) 方法是AnnotationConfigApplicationContext的应用上下文的类才有的方法,在添加完注解类后,需要调用refresh( )方法更新容器

@ComponentScan----组件扫描注解

作用:用于指定 spring 在初始化容器时要扫描的包。
在这里插入图片描述

@Configuration		//配置注解类
@ComponentScan(basePackages = "com.ccbx")		//包扫描注解
public class SpringConfig {
}

因为@Configuration是@Component的子注解,所以@Configuration注解的类也会被扫描并处理。

小技巧案例:

@Configuration      //配置注解类
public class ConfigurationAnno {
    @Bean
    public User user(){
        return new User(student()); //使用方法获取 bean【只能在@Configuration的注解类中才生效】
    }
    @Bean
    public Student student(){
        return new Student();
    }
}

@Import----配置类导入注解

作用:用于导入其他配置类,被导入的配置类,可以不写@Configuration 注解。

@Configuration	//配置注解
@Import({AppConfig.class})	//导入其他配置类
public class OtherConfig{
}

四、Spring整合Junit

  Junit 它无法知晓我们是否使用了Spring 框架,更不用说帮我们创建spring 容器了。不过Junit 给我们暴露了一个注解,可以让我们替换掉它的运行器。
  这时,我们需要依靠 spring 框架,因为它提供了一个运行器,可以读取XML配置文件(或注解)来创建容器。【替换为Spring的运行器】

整合步骤:

4.1 添加依赖


<dependency>
    <groupId>org.springframeworkgroupId>
    <artifactId>spring-testartifactId>
    <version>5.2.6.RELEASEversion>
    <scope>testscope>
dependency>

4.2 @RunWith注解替换原有运行器

@RunWith(SpringJUnit4ClassRunner.class)

4.3 @ContextConfiguration读取配置文件或注解

作用:该注解告诉spring是加载基于纯注解的配置类,还是加载XML配置文件。

  1. 如果加载XML配置文件,就使用value或者locations属性指定配置文件路径。
//多个XML文件之间用逗号隔开
//如果要加载XML配置文件【如果只有一个配置文件则{}可以省略】
@ContextConfiguration(locations = {"classpath:beans.xml"})
  1. 如果加载配置类,就用classes属性指定配置类的字节码。
//多个配置类的class文件之间用逗号隔开
@ContextConfiguration(classes = {BeanConfig.class,SpringConfig.class})

以上两个注解在测试类上写好后,就能在运行时,自动的获取spring容器(AnnotationConfigApplicationContext或者ApplicationContext类型),自动创建bean(如果bean标签配套使用了@Lazy的话,则需要时才加载)。

4.4 @Autowired注入数据

@RunWith(SpringJUnit4ClassRunner.class)		//替换原有运行器
@ContextConfiguration(classes = {SpringConfig.class})		//读取配置文件或注解
//@ContextConfiguration(locations ={"classpath:beans.xml"})
public class SpringJunitTest {
    //根据类型注入一个对象
    @Autowired
    private UserDao userDao;
    
    @Autowired
    private Student stu;

	//测试方法
    @Test
    public void test01() {
        System.out.println(userDao);
    }
 }

Spring IoC容器(XML&注解配置+Java代码配置+整合Junit4+Junit5)_第5张图片

4.5 【拓展】Spring 整合 Junit5

1.引入Junit5的依赖

<dependency>
    <groupId>org.junit.jupitergroupId>
    <artifactId>junit-jupiter-apiartifactId>
    <version>5.3.0version>
    <scope>testscope>
dependency>

2.测试类中添加集成Junit5的注解

@ExtendWith({SpringExtension.class})
@ContextConfiguration( "classpath:beans.xml")
//如果是加载配置类,第2个注解换成 @ContextConfiguration(classes = {配置类.class})
//简写:以上两个注解可被@SpringJUnitConfig代替
@SpringJUnitConfig({TxConfig.class})

你可能感兴趣的:(Spring,spring,java,xml)