Spring Bean的生命周期,就是一个Bean在IOC容器中从创建到销毁的过程
1、生命周期概要流程
简单来说,一个Bean的生命周期分为四个阶段:
-
实例化(Instantiation)
-
属性设置(populate)
-
初始化(Initialization)
-
销毁(Destruction)
具体逻辑位于AbstractAutowireCapableBeanFactory类doCreateBean方法中,代码较多,只放出了重要的部分,如下:
// AbstractAutowireCapableBeanFactory.java
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// 1. 实例化
BeanWrapper instanceWrapper = null;
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object exposedObject = bean;
try {
// 2. 属性赋值
populateBean(beanName, mbd, instanceWrapper);
// 3. 初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
// 4. 销毁-注册回调接口
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
return exposedObject;
}
上面的实例化、属性赋值、初始化都是Spring容器启动时的步骤,销毁是在容器关闭时的操作,容器销毁时会调用容器的close()方法去销毁容器。
2、对生命周期的扩展
Bean的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:
类型 | 描述 | 作用范围 |
---|---|---|
Bean自身的方法 | 这个包括了Bean本身调用的方法和通过配置文件中<bean>的init-method和destroy-method指定的方法 | 初始化之前,销毁之前 |
容器级生命周期接口方法 | 这个包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”。==作用于所有Bean的接口== | 对象初始化前后 |
工厂后处理器接口方法 | 这个包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工厂后处理器接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。 | 实例化对象之前 |
Bean级生命周期接口方法 | 这个包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这些接口的方法,==作用于单个Bean的接口,需要每个bean单击实现接口== | 对象初始化之前 |
加上这些扩展,现在上面的图可以变成下面这样了:
3、Bean自身的方法
Bean自身的方法包括了Bean本身调用的方法和通过配置文件中<bean>的init-method和destroy-method指定的方法
- 创建实体类
public class Person {
private String name;
private String address;
private String phone;
public Person() {
System.out.println("【构造器】调用Person的构造器实例化");
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("【注入属性】注入属性name");
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
System.out.println("【注入属性】注入属性address");
this.address = address;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
System.out.println("【注入属性】注入属性phone");
this.phone = phone;
}
// 通过<bean>的init-method属性指定的初始化方法
public void myInit() {
System.out.println("【init-method】调用<bean>的init-method属性指定的初始化方法");
}
// 通过<bean>的destroy-method属性指定的初始化方法
public void myDestory() {
System.out.println("【destroy-method】调用<bean>的destroy-method属性指定的初始化方法");
}
}
- 配置文件如下
<bean id="person" class="com.XXX.entity.Person" init-method="myInit" destroy-method="myDestory" scope="singleton" >
<property name="name" value="tom"/>
<property name="address" value="西安"/>
<property name="phone" value="13800000000"/>
</bean>
- main方法测试
System.out.println("现在开始初始化容器");
ApplicationContext ac = new ClassPathXmlApplicationContext("spring-config.xml");
System.out.println("容器初始化成功");
//得到Preson,并使用
Person person = ac.getBean("person",Person.class);
System.out.println(person);
System.out.println("现在开始关闭容器!");
((ClassPathXmlApplicationContext)ac).registerShutdownHook();
- 结果
4、容器级生命周期接口方法
BeanPostProcessor接口包括2个方法:
postProcessAfterInitialization和postProcessBeforeInitialization,
这两个方法的第一个参数都是要处理的Bean对象,第二个参数都是Bean的name。
- BeanPostProcessor
BeanPostProcessor作用在对象初始化之前后
定义类实现BeanPostProcessor
public class MyBeanPostProcessor implements BeanPostProcessor {
public MyBeanPostProcessor() {
super();
System.out.println("这是BeanPostProcessor实现类构造器!!");
// TODO Auto-generated constructor stub
}
@Override
public Object postProcessAfterInitialization(Object arg0, String arg1)
throws BeansException {
String str = bean.getClass().getName();//通过反射,我们可以得到当前加载的类的信息
System.out.println(str);//输出类的名称
System.out
.println("BeanPostProcessor接口方法postProcessAfterInitialization对属性进行更改!");
return arg0;
}
@Override
public Object postProcessBeforeInitialization(Object arg0, String arg1)
throws BeansException {
System.out
.println("BeanPostProcessor接口方法postProcessBeforeInitialization对属性进行更改!");
return arg0;
}
}
xml文件配置
<bean id="myBeanPostProcessor" class="com.XXX.config.MyBeanPostProcessor"/>
测试结果如下
由于这里只配置了一个Person,所以只看Person的效果,如果配置了多个bean,都可以看到效果
- InstantiationAwareBeanPostProcessor
InstantiationAwareBeanPostProcessor 作用对象实例化前后
InstantiationAwareBeanPostProcessor 接口本质是BeanPostProcessor的子接口,如下:
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
public MyInstantiationAwareBeanPostProcessor() {
super();
System.out.println("这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!");
}
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("InstantiationAwareBeanPostProcessor调用postProcessBeforeInstantiation方法");
return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInstantiation(beanClass, beanName);
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("InstantiationAwareBeanPostProcessor调用postProcessAfterInstantiation方法");
return InstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName);
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
System.out.println("InstantiationAwareBeanPostProcessor调用postProcessProperties方法");
return InstantiationAwareBeanPostProcessor.super.postProcessProperties(pvs, bean, beanName);
}
}
配置文件
<bean id="myInstantiationAwareBeanPostProcessor"
class="com.XXX.config.MyInstantiationAwareBeanPostProcessor">
</bean>
测试结果如下
5、工厂后处理器接口方法
在初始化之前执行,演示工厂后处理器接口方法,如下:
MyBeanFactoryPostProcessor
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public MyBeanFactoryPostProcessor() {
super();
System.out.println("这是BeanFactoryPostProcessor实现类构造器!!");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0) throws BeansException {
System.out.println("BeanFactoryPostProcessor调用postProcessBeanFactory方法");
BeanDefinition bd = arg0.getBeanDefinition("person");
bd.getPropertyValues().addPropertyValue("phone", "110");
}
}
配置文件
<bean id="beanFactoryPostProcessor"
class="com.XXX.config.MyBeanFactoryPostProcessor"></bean>
测试结果
6、Bean级生命周期接口方法
在初化对象之前 ,可以让实体类实现BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这4个接口
修改Person类结构,直接实现上面对应的接口
public class Person implements BeanFactoryAware, BeanNameAware,
InitializingBean, DisposableBean {
private String name;
private String address;
private String phone;
private BeanFactory beanFactory;
private String beanName;
public Person() {
System.out.println("【构造器】调用Person的构造器实例化");
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("【注入属性】注入属性name");
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
System.out.println("【注入属性】注入属性address");
this.address = address;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
System.out.println("【注入属性】注入属性phone");
this.phone = phone;
}
// 通过<bean>的init-method属性指定的初始化方法
public void myInit() {
System.out.println("【init-method】调用<bean>的init-method属性指定的初始化方法");
}
// 通过<bean>的destroy-method属性指定的初始化方法
public void myDestory() {
System.out.println("【destroy-method】调用<bean>的destroy-method属性指定的初始化方法");
}
// 这是BeanFactoryAware接口方法
@Override
public void setBeanFactory(BeanFactory arg0) throws BeansException {
System.out.println("【BeanFactoryAware接口】调用BeanFactoryAware.setBeanFactory()");
this.beanFactory = arg0;
}
// 这是BeanNameAware接口方法
@Override
public void setBeanName(String arg0) {
System.out.println("【BeanNameAware接口】调用BeanNameAware.setBeanName()");
this.beanName = arg0;
}
// 这是InitializingBean接口方法
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("【InitializingBean接口】调用InitializingBean.afterPropertiesSet()");
}
// 这是DiposibleBean接口方法
@Override
public void destroy() throws Exception {
System.out.println("【DiposibleBean接口】调用DiposibleBean.destory()");
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
", phone='" + phone + '\'' +
", beanFactory=" + beanFactory +
", beanName='" + beanName + '\'' +
'}';
}
}
测试结果如下