在使用Spring框架开发应用的过程中,大家都知道使用Spring开发应用程序,我们应用程序中所有的Bean都是通过Spring的IOC容器来管理。将Bean注入到Spring IOC容器中的方式多种多样,如通过传统的XML方式注入,通过注解的方式注入等。本文我们就通过例子的形式看一看如何通过注解@Configuration和@Bean向容器中注入组件。
1、首先创建一个Maven项目,加入spring-context和Junit依赖。
org.springframework
spring-context
5.1.5.RELEASE
junit
junit
4.12
test
2、创建一个类Computer(我们需要注入的Bean)
public class Computer {
private String name;
private String brand;
public Computer() {
System.out.println("创建Computer对象... ...");
}
public Computer(String name, String brand) {
super();
this.name = name;
this.brand = brand;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
@Override
public String toString() {
return "Computer [name="+name+",brand="+ brand +"]";
}
}
3、创建一个配置类BeanConfig
//配置类==配置文件
@Configuration //告诉Spring这是一个配置类
public class BeanConfig {
/**
* 向容器中注册一个Bean,类型为返回值类型,id默认为方法名称
* @return
*/
@Bean
public Computer computer() {
return new Computer("Latitude","Dell");
}
}
@Configuration:该注解所标记的类在Spring中就是一个配置类,被该注解所标记的类中包含一个或者多个@Bean注解的方法,这些被@Bean注解的方法将会被Spring容器扫描并用于构建Bean的定义,初始化Spring的IOC容器。
@Bean:被注解的方法将会生成一个可以被Spring IOC容器管理的Bean。
4、获得容器,测试Bean是否被注入
public class IOCTest1 {
@Test
public void testIOC(){
AnnotationConfigApplicationContext applicatoin = new AnnotationConfigApplicationContext(BeanConfig.class);
System.out.println("容器创建完成... ...");
String[] names = applicatoin.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
Object computer = applicatoin.getBean("computer");
System.out.println(computer);
Object computer1 = applicatoin.getBean("computer");
System.out.println(computer == computer1);
}
}
这里需要注意:
通过XML的方式向容器中注入Bean,我们用的是ClassPathXmlApplicationContext容器并传入XML文件的位置,通过注解的形式向容器中注入Bean时,我们用的是AnnotationConfigApplicationContext容器,传入的是Bean的配置类BeanConfig.class。
执行以上的单元测试,我们将会得到如下结果:
容器创建完成... ...
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
beanConfig
computer
Computer [name=Latitude,brand=Dell]
true
从运行结果我们可以得知如下的一些结论:
5、Bean实例的初始化及销毁
通过注解的方式向IOC容器中注入Bean时,可以通过设置@Bean注解的属性值来指定在创建对象时的初始化方法、销毁方法以及Bean的id等。
@Bean常用的属性如下:
修改BeanConfig类的@Bean注解如下:
@Bean(name="testComputer",initMethod="init",destroyMethod="destroy")
public Computer computer() {
return new Computer("Latitude","Dell");
}
指定Bean的名称为testComputer,初始化方法为init,销毁方法为destroy。
在Computer类中加入init、destroy方法。
public class Computer {
//... ...
protected void init() {
System.out.println("Init方法被调用... ...");
}
protected void destroy() {
System.out.println("Destroy方法被调用... ...");
}
}
修改测试方法如下:
public class IOCTest1 {
@Test
public void testIOC(){
AnnotationConfigApplicationContext applicatoin = new AnnotationConfigApplicationContext(BeanConfig.class);
System.out.println("容器创建完成... ...");
String[] names = applicatoin.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
Object computer = applicatoin.getBean("testComputer");
System.out.println(computer);
Object computer1 = applicatoin.getBean("testComputer");
System.out.println(computer == computer1);
applicatoin.close();
System.out.println("容器关闭了... ...");
}
}
执行测试方法我们可得到如下结果:
创建Computer对象... ...
Init方法被调用... ...
容器创建完成... ...
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
beanConfig
testComputer
Computer [name=Latitude,brand=Dell]
true
Destroy方法被调用... ...
容器关闭了... ...
从执行结果我们可以得知如下结论:
6、懒加载(@Lazy)
我们上面所说的Bean实例的创建都是在容器启动之后立马就会创建并执行对应的初始化方法,那么在单例模式下,如果我们希望在容器创建完成之后不用立马就创建实例,而是希望在我们第一次使用Bean时才创建对象并完成对应的初始化动作,然后再将对象放到IOC容器中。
Spring为我们提供了@Lazy注解,当我们对Bean加上该注解之后,在单例模式下,Spring IOC容器就能够控制在容器创建时就创建对象还是在第一次使用时创建对象。
修改BeanConfig类如下:
@Configuration //告诉Spring这是一个配置类
public class BeanConfig {
/**
* 向容器中注册一个Bean,类型为返回值类型,id默认为方法名称
* @return
*/
@Bean(name="testComputer",initMethod="init",destroyMethod="destroy")
@Lazy
public Computer computer() {
return new Computer("Latitude","Dell");
}
}
我们在Bean上加了@Lazy注解,执行单元测试我们将会得到如下结果:
容器创建完成... ...
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
beanConfig
testComputer
创建Computer对象... ...
Init方法被调用... ...
Computer [name=Latitude,brand=Dell]
true
Destroy方法被调用... ...
容器关闭了... ...
从执行结果我们可以得知:
7、多实例配置(@Scope)
默认情况下,Spring IOC容器都是以单例的模式来管理Bean,如果我们要创建多个实例怎么办?Spring提供了@Scope注解,我们通过该注解制定Bean的作用域,可以控制在IOC容器中Bean实例是以单例还是其他的方式存在。
@Scope有如下几个值:
修改BeanConfig类如下:
@Configuration //告诉Spring这是一个配置类
public class BeanConfig {
/**
* 向容器中注册一个Bean,类型为返回值类型,id默认为方法名称
* @return
*/
@Bean(name="testComputer",initMethod="init",destroyMethod="destroy")
@Scope("prototype")
public Computer computer() {
return new Computer("Latitude","Dell");
}
}
执行单元测试,得到如下结果:
容器创建完成... ...
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
beanConfig
testComputer
创建Computer对象... ...
Init方法被调用... ...
Computer [name=Latitude,brand=Dell]
创建Computer对象... ...
Init方法被调用... ...
false
容器关闭了... ...
根据结果我们可得出如下结论:
小结:
本文我们通过注解的方式演示了如何向Spring IOC容器中注入Bean及如何获取一个Bean实例,同时演示了如何初始化Bean、如何销毁Bean,以及如何设置Bean的作用域及@Scope的值所代表的含义,同时介绍了在单例模式下如何设置在第一次使用Bean时才创建Bean实例,希望对大家有所帮助。