Bean生命周期

前言

在学习Spring框架的IOC、AOP两大功能之前,首先需要了解这两个技术的基础——Bean。在Spring框架中,Bean无处不在,IOC容器管理的对象就是各种各样的Bean。理解Bean的生命周期有助于我们更好的理解和使用Spring框架的IOC功能,也有助于我们理解框架如何初始化、使用和管理Bean。接下来我们通过代码实现观察BeanFactory与ApplicationContext中bean的生命周期。

BeanFactory中Bean的生命周期

原理

BeanFactory在Spring框架中被称为IOC容器,是Spring框架的基础设施,面向Spring本身;Spring框架作者将其比作Spring的心脏,可见其在框架中的重要性。BeanFactory中bean的生命周期如图1所示。

1564068334910

图1 BeanFactory中bean的生命周期

  • 其中橙色和绿色的是容器级别生命周期接口,也就是所有的Bean初始化时都会发生作用。主要包含两个接口InstantiationAwareBeanPostProcessor、BeanPostProcessor,一般被称为类后处理器。也可根据BeanName进行过滤对指定的Bean进行后处理。

  • 蓝色的是Bean级生命周期接口方法,只有实现了这些接口的Bean进行初始化时,才会起作用。包含BeanNameAware、BeanFactoryAware、InitializingBean、DisposableBean。

  • 灰色的是Bean自身的方法,通过Bean定义构造函数、setter属性赋值函数、init-method和destroy-method所指定的方法。

实例

参照《Spring 4.x企业应用开发实战》中的car创建验证Bean的生命周期。

  1. 首先定义CarBean类,实现Bean级别的各个接口,如下代码所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class CarBean implements BeanNameAware, BeanFactoryAware, InitializingBean, DisposableBean{

private String brand;
private String color;
private int maxSpeed;

private BeanFactory beanFactory;
private String beanName;
public CarBean() {
System.out.println("调用car构造函数");
}
// 省略属性set、get方法,一定要有set,否则xml定义bean时无法设置属性值
public void introduce() {
System.out.println("brand:" + brand + ", color:" + color + ", maxSpeed:" + maxSpeed);
}

public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("调用BeanFactoryAware.setBeanFactory()方法");
this.beanFactory = beanFactory;
}

public void setBeanName(String s) {
System.out.println("调用BeanNameAware.setBeanName()方法");
this.beanName = s;
}

public void destroy() throws Exception {
System.out.println("调用DisposableBean.destroy()方法");
}

public void afterPropertiesSet() throws Exception {
System.out.println("调用InitializingBean.afterPropertiesSet()方法");
}

public void myInit(){
System.out.println("调用init-method所指定的myInit()方法,将maxSpeed设置为240");
this.maxSpeed = 240;
}

public void myDestory() {
System.out.println("调用destory-method所指定的myDestory()方法");
}
}
  1. 自定义容器级别工厂后处理器,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("调用InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()方法");
return null;
}

public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("调用InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()方法");
return true;
}

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
System.out.println("调用InstantiationAwareBeanPostProcessor.postProcessProperties()方法");
return pvs;
}
}

public class MyBeanPostProcessor implements BeanPostProcessor {

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("调用BeanPostProcessor.postProcessBeforeInitialization()方法");
return null;
}

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("调用BeanPostProcessor.postProcessAfterInitialization()方法");
return null;
}
}
  1. 创建bean的xml文件,如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
<bean id="car" class="com.aily.bean.CarBean"
init-method="myInit"
destroy-method="myDestory"
p:brand="红旗CA72"
p:color="黑色"
p:maxSpeed="200"
/>
</beans>
  1. 编写主程序验证bean生命周期
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 public static void main(String[] args) {
Resource resource = new ClassPathResource("carbean.xml");
BeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader((DefaultListableBeanFactory) beanFactory);
reader.loadBeanDefinitions(resource);

((DefaultListableBeanFactory) beanFactory).addBeanPostProcessor(new MyInstantiationAwareBeanPostProcessor());
((DefaultListableBeanFactory) beanFactory).addBeanPostProcessor(new MyBeanPostProcessor());

CarBean carBean = (CarBean) beanFactory.getBean("car");
carBean.introduce();

carBean.setColor("红色");
CarBean carBean2 = (CarBean) beanFactory.getBean("car");

System.out.println("carBean == carBean2:" + (carBean == carBean2));

((DefaultListableBeanFactory) beanFactory).destroySingleton("car");

}

输出结果为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
"E:\Program Files\Java\jdk1.8.0_91\bin\java" "-javaagent:D:\Program ……
调用InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()方法
调用car构造函数
调用InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()方法
调用InstantiationAwareBeanPostProcessor.postProcessProperties()方法
设置属性值brand
设置属性值color
设置属性值maxSpeed
调用BeanNameAware.setBeanName()方法
调用BeanFactoryAware.setBeanFactory()方法
调用BeanPostProcessor.postProcessBeforeInitialization()方法
调用InitializingBean.afterPropertiesSet()方法
调用init-method所指定的myInit()方法,将maxSpeed设置为240
调用BeanPostProcessor.postProcessAfterInitialization()方法
brand:红旗CA72, color:黑色, maxSpeed:240
设置属性值color
carBean == carBean2:true
调用DisposableBean.destroy()方法
调用destory-method所指定的myDestory()方法

Process finished with exit code 0

从上输出结果可验证Bean生命周期的流程。由于bean默认是单例模式,故在第二次调用getBean时,并没有触发生命周期初始化流程,而是从Spring缓存池中获取bean实例。若将bean的scope属性设置为prototype,则每次调用getBean都会创建一个新的Bean,生命周期方法会被再次调用。

ApplicationContext中的生命周期

在Spring容器ApplicationContext中,bean的生命周期与Bean中类似。区别是增加了BeanFactoryPostProcessor后处理器的postProcessBeanFactory方法以及ApplicationContextAware的setApplicationContext方法。Bean生命周期如下图所示:

1565107090729

图2 ApplicationContext中的Bean生命周期

修改xml配置文件,将自定义的MyBeanFactoryPostProcessor配置到xml文件里。修改后的xml文件如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">

<bean id="myBeanFactoryPostProcessor" class="com.aily.bean.MyBeanFactoryPostProcessor"/>
<bean id="car" class="com.aily.bean.CarBean" scope="singleton"
init-method="myInit"
destroy-method="myDestory"
p:brand="红旗CA72"
p:color="黑色"
p:maxSpeed="200"
/>
</beans>

MyBeanFactoryPostProcessor的类代码为:

1
2
3
4
5
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor{
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
System.out.println("调用BeanFactoryPostProcessor.postProcessBeanFactory()方法");
}
}

调用ApplicationContext的getBean生成Bean,输出结果为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
"E:\Program Files\Java\jdk1.8.0_91\bin\java" "-javaagent:D:\Program ……org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'myBeanFactoryPostProcessor'
调用BeanFactoryPostProcessor.postProcessBeanFactory()方法
00:04:04.962 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'car'
调用car构造函数
设置属性值brand
设置属性值color
设置属性值maxSpeed
调用BeanNameAware.setBeanName()方法
调用BeanFactoryAware.setBeanFactory()方法
调用ApplicationContextAware.setApplicationContext()方法
调用InitializingBean.afterPropertiesSet()方法
调用init-method所指定的myInit()方法,将maxSpeed设置为240
brand:红旗CA72, color:黑色, maxSpeed:240

Process finished with exit code 0