本文主要是介绍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标签时,需要在<beans>根元素中添加context的命名空间和命名空间相应的XML结构定义文档的位置,两者是成对配置的。
<?xml version="1.0" encoding="UTF-8"?>
<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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://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
等组件的注解功能。要开启此类型注解,需要进行路径扫描的配置:【推荐使用】
<!-- 开启组件扫描;1.base-package属性用于设置扫描的路径,是告诉spring要扫描的包;2.使用该配置,容器对该包及子包下标注@Component注解的类进行实例化。-->
<context:component-scan base-package="com.java" />
【注意】如果配置了component-scan,就不需要配置annotation-config的配置了!
【扩展】
- 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和注入依赖的方式来说,就是检查该属性对应的<prpperty>
是否被正确配置。【@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;}
}
【注意】
- 如果user属性注入user的配置被注释了(注释
<property>
标签),则在容器启动时会抛出BeanInitializationException 异常
提示!- @Autowired默认是required的,也就是备注接的依赖对象必须已经在容器中注册。如果没有,则抛出
UnsatisfiedDependencyException 异常
,容器初始化失败。
@Autowired----依赖对象的自动装配
@Autowired注解,直接在代码中进行依赖对象的自动装载。【依赖对象的注入】【@Autowired
会自动在容器中查找依赖项并注入】(该注解是根据Bean的类型来查找,有多个类型相同得对象时再根据名字来查找依赖对象。)
@Autowired注解
可以使用在 类构造器、属性、属性Setter方法、一般方法 上。
@AutoWired是spring的注解,
Autowired只根据type进行注入,不会去匹配name
。如果涉及到type无法辨别注入对象时,那需要依赖 @Qualifier 或 @Primary 注解一起来修饰。
- 在构造器中使用
@Autowired
@Autowired
public BookDao(Book book){this.book = book;
}
- 在Setter方法和一般方法中使用
@Autowired
@Autowired //在Setter方法中使用
public void setBook(Book book){this.book = book;
}@Autowired //在一般方法中使用
public void initUser(User user){this.user = user;
}
【注意】这里注解
@Autowired
的一般方法虽然没有被调用,容器也会将依赖对象注入,从而设置user属性的值。
- 在属性中应用
@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;
}
【注意】
@Autowired
默认根据类来查找和注入容器中管理的对象,对于注解的属性和参数依赖要确保响应的Bean被容器托管(对XML而言,要在其中定义相应的Bean),否则容器在初始化的时候就会找不到依赖对象而无法正常启动。- 如果多个Bean对应一个类的话,则使用该类集合类型装载就可以得到该类的所有Bean的集合,集合类型包括该类的Array[]、Set、Map。(上方已给出)
- @Autowired默认是required的,也就是备注接的依赖对象必须已经在容器中注册。如果没有,则抛出
UnsatisfiedDependencyException 异常
,容器初始化失败。和@Required注解的效果一致(但有区别)。- 如果程序在运行时才需要注入Bean,而不是在容器初始化时进行装配注入,这种情况下可以通过设置
required=false
的属性值,取消在容器初始化时对依赖对象的检查。也可以在方法参数上使用@Nullable 注解
达到同样效果。【上面例子已列出】- @Autowired可以用来自动装配自定义类的Bean,也可以用来装配容器的上下文和容器对象,包括
BeanFactory
、ApplicationContext
、Environment
、ResourceLoader
、ApplicationEventPublisher
、MessageSource
等。- 显示依赖注入会覆盖自动装配。
@Compronent----组件注解
通过@Autowired 注解
将 依赖注入从XML配置转到Java代码中,更进一步,可以将Bean的定义也放到Java代码中使用注解的方式进行配置。
在类中使用@Component 注解
,容器可以在启动时进行该类的实例化。【该注解及其子注解是使用在类层级的组件注解】
通过配置<context:component-scan> 标签
即可开启@Component 注解功能,默认状况下会扫描 base-package 包下的所有 @Component 和 子注解(@Repository、@Service、@Controller)标注的类进行实例化并注册。
在该注解的基础上定义了不同层级的子注解,如下:
@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()
方式获取。
案例:
@Lazy----组件懒加载注解
作用:设置bean的懒加载,相当于<bean lazy-init=”true”>
。
@Value----基本类型注入的注解
作用:注入基本类型(包装类型)和String 类型数据。
注意:该注解所在的类必须是在 IoC 容器中!(即必须是一个容器中的Bean)
@Value("520") //给基本类型的包装类型注入数据
private Integer num;
@Value("这是一个注入的字符串的值") //给String类型注入数据
private String str;
- 修饰的属性不需要提供私有属性的set方法 。(内部自动去操作私有属性,通过反射给属性赋值)
@PropertySource----指定资源文件位置的注解
作用:用于加载.properties配置文件。
例如我们配置数据源时,可以把连接数据库的信息写到properties 配置文件中,就可以使用此注解指定 properties 配置文件的位置。
value 属性
:用于指定 properties 文件位置。如果是在类路径下,需要加上classpath:
【注意】
- 上面用了
@Value(“${xxx}”)
,它是将properties文件中的value注入给类的成员变量,xxx就是key。- 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的<bean>
配置中使用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----配置类注解
@Configuration
也是一种组件类型的注解。
使用 @Configuration 注解的类相当于XML配置的<beans>
元素,该类中的方法使用 @Bean 注解注册组件,相当于XML配置中的<bean>
元素。
@Configuration //配置类注解
public class AppConfig{@Bean //组件注解【默认注册的实例id=user即方法名】public User user(){return new User();}
}
以上效果等同于XML配置
<beans> <!-- XML配置文件根元素 --><bean class="com.ccbx.pojo.User" /><!-- Bean配置 -->
</beans>
【注意】
- 在非@Configuration注解类的@Bean注解方法中不能定义Bean之间的依赖关系,如果定义在非@Configuration注解类的依赖关系中,则有可能被当做一般的方法被调用,而不是用来作为Bean定义的方法。
容器初始化----Java代码配置
XML的容器的配置方式
使用ClassPathXmlApplicationContext
、FileSystemXmlApplicationContext
、GenericXmlApplicationContext
来读取配置文件并初始化容器,代码配置方式
使用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(); //更新容器
【注意】
- register( ) 方法是AnnotationConfigApplicationContext的应用上下文的类才有的方法,在添加完注解类后,需要
调用refresh( )方法更新容器
。
@ComponentScan----组件扫描注解
作用:用于指定 spring 在初始化容器时要扫描的包。
@Configuration //配置注解类
@ComponentScan(basePackages = "com.ccbx") //包扫描注解
public class SpringConfig {
}
因为@Configuration是@Component的子注解,所以@Configuration注解的类也会被扫描并处理。
小技巧案例:
@Configuration //配置注解类
public class ConfigurationAnno {@Beanpublic User user(){return new User(student()); //使用方法获取 bean【只能在@Configuration的注解类中才生效】}@Beanpublic 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 添加依赖
<!-- spring整合junit的依赖 -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.2.6.RELEASE</version><scope>test</scope>
</dependency>
4.2 @RunWith注解替换原有运行器
@RunWith(SpringJUnit4ClassRunner.class)
4.3 @ContextConfiguration读取配置文件或注解
作用:该注解告诉spring是加载基于纯注解的配置类,还是加载XML配置文件。
- 如果加载XML配置文件,就使用
value
或者locations
属性指定配置文件路径。
//多个XML文件之间用逗号隔开
//如果要加载XML配置文件【如果只有一个配置文件则{}可以省略】
@ContextConfiguration(locations = {"classpath:beans.xml"})
- 如果加载配置类,就用
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 {//根据类型注入一个对象@Autowiredprivate UserDao userDao;@Autowiredprivate Student stu;//测试方法@Testpublic void test01() {System.out.println(userDao);}}
4.5 【拓展】Spring 整合 Junit5
1.引入Junit5的依赖
<dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><version>5.3.0</version><scope>test</scope>
</dependency>
2.测试类中添加集成Junit5的注解
@ExtendWith({SpringExtension.class})
@ContextConfiguration( "classpath:beans.xml")
//如果是加载配置类,第2个注解换成 @ContextConfiguration(classes = {配置类.class})
//简写:以上两个注解可被@SpringJUnitConfig代替
@SpringJUnitConfig({TxConfig.class})
这篇关于Spring IoC容器(XML注解配置+Java代码配置+整合Junit4+Junit5)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!