Spring学习5(3)
Bean生命周期由多个特定的生命阶段组成,每个生命阶段都开出接口,允许外界由此对Bean施加控制。
在spring中有两个层面来定义Bean的生命周期,一个是Bean的作用范围,一个是实例化Bean时所经历的一系列阶段。
BeanFactory中Bean的生命周期
生命周期图解
具体调用过程如下:
- 当调用getBean()来请求某一个Bean时,如果容器注册了
org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor
接口则会在实例化Bean之前,将调用接口的postProcessBeforeInstantiation()
方法。 - 根据配置情况调用Bean构造函数或工厂方法实例化Bean。
- 如果容器注册了在步骤1中的那个接口那么在实例化Bean后,可以调用接口的
postProcessAfterInstantiation()
方法来对已经实例化的对象做一点“梳妆打扮”。 - 如果Bean配置了属性信息,那么容器在这一步将配置值设置到Bean对应属性中,不过在设置每个属性之前可以调用步骤1接口的
postProcessPropertyValues()
方法。 - 调用Bean的属性设置方法设置属性值。
- 如果Bean实现了
org.springframework.bean.factory.BeanNameAware
接口则将调用setBeanName()接口方法,将配置文件中该Bean对应的名称设置到Bean中。 - 如果Bean实现了
org.springframework.beans.factory.BeanFactoryAware
则将嗲用setBeanFactory()
方法将BeanFactory容器实例设置到Bean中。 - 如果BeanFactory装配了
org.springframework.beans.factory.config.BeanPostProcessor
,则调用BeanPostProcessor的Objetc:postProcessBeforeInitialization(Object bean, String beanName)
这个函数提供当前正在处理的Bean以及beanName(当前Bean的配置名)返回加工处理后的Bean。这个方法可以对某些Bean进行特殊的处理,甚至改变Bean的行为,是spring框架中的重要方法,为容器提供对Bean进行后续加工处理的切入点,spring容器所提供的各种功能如Aop,动态代理等都经过BeanPostProcessor来实施。 - 如果Bean实现了InitializingBean的接口afterPropertiesSet()方法。
- 如果在
<bean>
中通过了init-method定义了初始化方法,则将执行这个方法。 - BeanPostProcessor除了步骤8中的方法还定义了
postProcessAfterInitialization(Object bean, String beanName)
方法,此时会调用这个方法让容器再次获得对Bean进行加工的机会。 - 如果在
<bean>
中指定Bean的作用范围为scope="prototype"
则将Bean返回给调用者,spring不再管理Bean的生命周期;如果指定为scope="singletion"
则将Bean放入springIoC容器的缓存池中,并将Bean引用放回给调用者,spring继续对这些Bean进行后续的生命管理。 - 对于
scope="singleton"
的Bean(默认情况),当容器关闭时,如果Bean实现了DisposableBean接口,则将调用接口的destory()
方法,可以在此编写释放资源,记录日志等操作。 - 对于
scope="singletion"
的Bean,如果通过<bean>
的destroy-method属性指定了Bean的销毁方法,那么Spring将执行Bean的这个方法,完成Bean资源的释放。
Bean生命周期实例
采用之前用过的Car类,让它实现所有Bean级的生命接口。
我们修改com.smart下Car.java文件为如下代码:
package com.smart;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
public class Car implements BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean{
private String brand;
private String color;
private int maxSpeed;
private BeanFactory beanFactory;
private String beanName;
public Car() {
System.out.println("调用Car()构造函数。");
}
public Car(String brand, String color, int maxSpeed) {
this.brand = brand;
this.color = color;
this.maxSpeed = maxSpeed;
}
public void introduce() {
System.out.println("brand:"+brand+";color:"
+ color+";maxSpeed:"
+ maxSpeed+".");
}
public void setBrand(String brand) {
this.brand = brand;
System.out.println("调用setBrand()设置属性。");
}
public void setColor(String color) {
this.color = color;
System.out.println("调用setColor()设置属性。");
}
public void setMaxSpeed(int maxSpeed) {
this.maxSpeed = maxSpeed;
System.out.println("调用setMaxSpeed()设置属性。");
}
//BeanFactoryAwawre接口方法
public void setBeanFactory(BeanFactory beanFactory) throws BeansException{
System.out.println("调用BeanFactoryAware.setBeanFactory().");
this.beanFactory = beanFactory;
}
//BeanNameAware接口方法
public void setBeanName(String beanName) {
System.out.println("调用BeanNameAware.setBeanName().");
this.beanName = beanName;
}
//InitializingBean接口方法
public void afterPropertiesSet() throws Exception{
System.out.println("调用InitializingBean.afterPropertiesSet().");
}
//DisposableBean接口方法
public void destroy() throws Exception{
System.out.println("调用DisposableBean.destroy().");
}
//通过<bean>的init-method属性指定的初始化方法
public void myInit() {
System.out.println("调用init-method所指定的myInit(),将maxSpeed设置为240.");
this.maxSpeed = 240;
}
//通过<bean>的destroy-method属性指定的销毁方法
public void myDestroy() {
System.out.println("调用destroy-method所指定的myDestroy().");
}
}
这里实现了BeanFactoryAware, BeanNameAware,InitializingBean,DisposableBean等Bean级的生命周期接口,在下面定义了myInit()和myDestroy()方法,这两个方法就可以在<bean>
中通过init-method和destroy-method方法。
MyInstantiationAwareBeanPostProcessor通过扩展InstantiationAwareBeanPostProcessor适配器InstatiationAwareBeanPostProcessorAdapter提供实现。我们在com.smart.beanfactory中增加myInstantiationAwareBeanPostProcessor.java,代码如下:
package com.smart.beanfactory;
import java.beans.PropertyDescriptor;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.
InstantiationAwareBeanPostProcessorAdapter;
import com.smart.Car;
public class MyInstantiationAwareBeanPostProcessor extends
InstantiationAwareBeanPostProcessorAdapter{
//接口:在实例化Bean前调用
public Object postProcessBeforeInstantiation(Class beanClass, String beanName)
throws BeansException{
if("car1".equals(beanName)) {
System.out.println("InstantiationAware BeanPostProcessor.postProcess"
+ " BeforeInstantiation");
}
return null;
}
//接口:在实例化Bean后调用
public boolean postProcessAfterInstantiation(Object bean, String beanName)
throws BeansException{
if("car1".equals(beanName)) {
System.out.println("InstantiationAware BeanPostProcessor.postProcess"
+ " AfterInstantiation");
}
return true;
}
//接口:在设置某个属性时调用
public PropertyValues postProcessPropertyValues(
PropertyValues pvs,PropertyDescriptor[] pds, Object bean, String beanName)
throws BeansException{
if("car1".equals(beanName)) {
System.out.println("Instantiation AwareBeanPostProcessor.postProcess"
+ "PropertyValues");
}
return pvs;
}
}
除此之外spring还有一个BeanPostProcessor实现类,对配置文件所提供的属性设置值进行判断,并执行相应的“补缺补漏操作”,在代码清单如下:
package com.smart.beanfactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import com.smart.Car;
public class MyBeanPostProcessor implements BeanPostProcessor{
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException{
if(beanName.equals("car1")) {
Car car = (Car)bean;
if(car.getColor() == null) {
System.out.println("调用BeanPostProcessor.postProcess"
+ " BeforeInitialization(), color is empty, default color is black");
car.setColor("黑色");
}
}
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException{
if(beanName.equals("car1")) {
Car car = (Car)(bean);
if(car.getMaxSpeed() >= 200) {
System.out.println("调用BeanPostProcessor.postProcess"
+ "AfterInitialization(), modify maxSpeed to 200.");
car.setMaxSpeed(200);
}
}
return bean;
}
}
注册接口
上述这写接口除了在Car.java中直接定义的接口其他的接口都需要注册加载。首先我们在beans.xml中注册myInit和myDestroy方法。代码更改如下:
<bean id="car1" class="com.smart.Car"
init-method="myInit"
destroy-method="myDestroy"
p:brand="红旗CA72"
p:color="黑色"
p:maxSpeed="200"
/>
</beans>
下面让容器装载配置文件,然后分别注册上面所提供的两个后处理器。在com.smart.beanfactory下创建BeanLifeCycle.java文件,代码如下:
package com.smart.beanfactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import com.smart.Car;
public class BeanLifeCycle{
private static void LifeCycleInBeanFactory() {
//装载配置文件并启动容器
Resource res = new ClassPathResource("com/smart/beanfactory/beans.xml");
BeanFactory bf = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader((DefaultListableBeanFactory)bf);
reader.loadBeanDefinitions(res);
//向容器注册MyBeanPostProcessor后处理器
((ConfigurableBeanFactory)bf).addBeanPostProcessor(new MyBeanPostProcessor());
//向容器中注册MyInstantiationAwareBeanPostProcessor后处理器
((ConfigurableBeanFactory)bf).addBeanPostProcessor(new MyInstantiationAwareBeanPostProcessor());
//第一次从容器中获取car,将出发容器实例化Bean,将引发生命周期方法的调用
Car car1 = (Car)bf.getBean("car1");
car1.introduce();
car1.setColor("红色");
//第二次从容器中获取Car,直接从缓存池中获取
Car car2 = (Car)bf.getBean("car1");
//查看car1和car2是否指向同一引用
System.out.println("car1 == car2:" + (car1==car2));
//关闭容器
((DefaultListableBeanFactory)bf).destroySingletons();
}
public static void main(String[] args) {
LifeCycleInBeanFactory();
}
}
这里需要注意的是多个后处理器的调用顺序和注册顺序无关,必须通过实现org.springframework.core.Ordered
接口来确定调用顺序。
运行该代码即可基本了解调用的过程。
ApplicationContext中Bean的生命周期
书中给出的生命周期图如下:
可以看到在Application只是多了几个步骤:
- 如果Bean实现了
org.springframework.context.ApplicationContextAware
接口则会增加一个调用该接口方法setApplicationContext()
的步骤 - 如果在配置文件中申明了后处理接口
BeanFactoryPostProcessor
的实现类,则应用上下文在装载配置文件之后,初始化实例之前将调用BeanFactoryPostProcessor
对配置信息进行加工处理。
除此之外,ApplicationContext会利用java的反射机制自动识别出配置文件中定义的BeanPostProcessor等后处理器并注册到上下文中,而不像BeanFactory需要手工调用addBeanPostProcessor()进行注册。
实例
假设我们希望对配置文件中car1的brand配置属性进行调整。在com.smart.context创建一个MyBeanFactoryPostProcessor.java,代码如下:
package com.smart.context;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import com.smart.Car;
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor{
//对car的brand配置信息进行加工操作
public void postProcessBeanFactory(ConfigurableListableBeanFactory bf)
throws BeansException{
BeanDefinition bd = bf.getBeanDefinition("car1");
bd.getPropertyValues().addPropertyValue("brand", "奇瑞QQ");
System.out.println("调用BeanFactoryPostProcessor.postProcessBean Factory()");
}
}
ApplicationContext在启动时,将首先为配置文件中的每一个<bean>
生成一个BeanDefinition对象(<bean>
在spring容器中的内部表示)而后我们就有机会对其进行修改。
接下来对beans.xml修改:
<bean id="car1" class="com.smart.Car"
init-method="myInit"
destroy-method="myDestroy"
p:brand="红旗CA72"
p:color="黑色"
p:maxSpeed="200"
/>
<bean id = "myBeanFactoryPostProcessor"
class = "com.smart.context.MyBeanFactoryPostProcessor"/>