文章目录
Spring Bean的生命周期
1、示例引入
1、定义bean
//定义一个Car,实现Bean的4个生命周期级接口
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 void setBrand(String brand) {
System.out.println("调用setBrand()方法");
this.brand = brand;
}
public void introtuce() {
System.out.println( "brand:" + brand + ";color:'" + color +";maxSpeed:" + maxSpeed);
}
//1、BeanFactoryAware接口:注入一个工厂对象
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("调用BeanFactoryAware.setBeanFactory()。");
this.beanFactory = beanFactory;
}
//2、BeanNameAware接口:setBeanName(String name)注入bean的名称
@Override
public void setBeanName(String name) {
System.out.println("调用BeanNameAware.setBeanName()。");
this.beanName = name;
}
//3、InitializingBean接口:完成初始化逻辑
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("调用InitializingBean.afterPropertiesSet()。");
}
//4、DisposableBean接口:完成销毁逻辑
@Override
public void destroy() throws Exception {
System.out.println("调用DisposableBean.destroy()。");
}
//5、通过<bean>的init_method属性指定初始化方法
public void myInit(){
System.out.println("调用init-method所指定的myInit(),将maxSpeed设置为240");
this.maxSpeed=240;
}
//6、通过<bean>的destory_method属性指定销毁方法
public void myDestory(){
System.out.println("调用destory-method所指定的myDestory()");
}
...省略get()和set()方法.....
}
2、后置处理器1
/**
* 在这个类中通过过滤条件仅对car Bean进行处理,对其他Bean一概视而不见
*/
public class MyInstantiationAwareBeanPostProcessor
extends InstantiationAwareBeanPostProcessorAdapter {
/**
* 1、父类方法:在实例化Bean之前调用
*/
@Override
public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {
//仅对容器中的Car bean做处理
if("car".equals(beanName)){
System.out.println("调用MyInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()");
}
return null;
}
/**
* 2、父类方法:在实例化Bean之后调用
*/
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
//仅对容器中Car Bean处理
if("car".equals(beanName)){
System.out.println("调用MyInstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()");
}
return true;
}
/**
* 3、父类方法:在设置某个属性时调用
*/
@Override
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
//仅对car中某个特定属性进行处理
if(beanName.equals("car")){
System.out.println("调用MyInstantiationAwareBeanPostProcessor.postProcessPropertyValues()");
}
return pvs;
}
}
3、后置处理器2
/**
* 在这个类中仅对Car Bean进行处理:
* 对配置文件所提供的属性设置值进行判断,并执行相应的“补缺查漏”操作
*/
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(beanName.equals("car")){
Car car = (Car) bean;
if(car.getColor()==null){
System.out.println("调用MyBeanPostProcessor.postProcessBeforeInitialization() ,color为空,设置为黑色");
car.setColor("黑色");
}
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if(beanName.equals("car")){
Car car = (Car) bean;
if(car.getMaxSpeed()>=200){
System.out.println("调用MyBeanPostProcessor.postProcessAfterInitialization() ,将maxSpeed调整为200");
car.setMaxSpeed(200);
}
}
return bean;
}
}
4、beans.xml的配置
<bean id="car"
class="com.hh.bean.Car"
init-method="myInit"
destroy-method="myDestory">
<property name="brand" value="红旗CA72"/>
<property name="maxSpeed" value="200"/>
</bean>
5、注册两个后置处理器
让容器装载配置文件,然后分别注册上面所提供的两个后置处理器,这里是Bean的生命周期的关键:
/**
* 让容器装载配置文件,然后分别注册上面所提供的两个后置处理器
*
* 1、对BeanFactory类型的beanFactory变量进行强制装换,
* 是因为addBeanPostProcessor()在ConfigurableBeanFactory接口中
* 2、后置处理器的时机地哦啊用顺序和注册顺序无关,在有多个后置处理器的情况下
* 必须通过实现org.springframework.core.Ordered接口来确定调用顺序
*
* 3、第一次获取bean,容器将按照生命周期过程,实例化Car并放入缓存池中,然后返回给调用者
* 第二次从容器中获取Car,直接从缓存池中获取,不会引发生命周期相关方法的执行
* 如果将scope=prototype,第二次获取bean时,生命周期方法会再次被调用,因为每次返回新实例
*/
public class BeanLifeCycle {
public static void main(String[] args) {
LifeCycleInBeanFactory();
}
public static void LifeCycleInBeanFactory(){
//1、封装配置文件:将配置文件封装为Resource类型的实例方法
Resource res = new ClassPathResource("beans.xml");
//2、启动容器:xmlBeanFactory的初始化
BeanFactory beanFactory = new DefaultListableBeanFactory();
//3、加载配置文件
XmlBeanDefinitionReader reader
= new XmlBeanDefinitionReader((DefaultListableBeanFactory)beanFactory);
reader.loadBeanDefinitions(res);
//4、向容器中注册MyBeanPostProcessor后处理器
((ConfigurableBeanFactory)beanFactory).addBeanPostProcessor(new MyBeanPostProcessor());
//5、向容器中注册MyInstantiationAwareBeanPostProcessor
((ConfigurableBeanFactory)beanFactory).addBeanPostProcessor(new MyInstantiationAwareBeanPostProcessor());
//6、第一次从容器中获取car,将触发容器初始化Bean,将引发Bean生命周期方法的调用
Car car1 = (Car) beanFactory.getBean("car");
car1.introtuce();
car1.setColor("红色");
//7、第二次从容器中获取Car,直接从缓存池中获取
Car car2 = (Car)beanFactory.getBean("car");
System.out.println("car1==car2:"+ (car1==car2));
//8、关闭容器
((DefaultListableBeanFactory)beanFactory).destroySingletons();
}
}
运行结果:
调用MyInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
调用Car()的构造函数
调用MyInstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
调用MyInstantiationAwareBeanPostProcessor.postProcessPropertyValues()
调用setBrand()方法
调用BeanNameAware.setBeanName()。
调用BeanFactoryAware.setBeanFactory()。
调用MyBeanPostProcessor.postProcessBeforeInitialization() ,color为空,设置为黑色
调用InitializingBean.afterPropertiesSet()。
调用init-method所指定的myInit(),将maxSpeed设置为240
调用MyBeanPostProcessor.postProcessAfterInitialization() ,将maxSpeed调整为200
brand:红旗CA72;color:'黑色;maxSpeed:200
car1==car2:true
调用DisposableBean.destroy()。
调用destory-method所指定的myDestory()
2、BeanFactory中bean的生命周期
-
当调用者通过
getbean(beanName)
向容器中请求一个Bean时,如果容器注册了InstantiationAwareBeanPostProcessor
接口,就会在Bean实例化之前调用接口的postProcessBeforeInstantiation()
方法 -
根据情况调用Bean构造方法或者工厂方法实例化Bean
-
如果容器注册了
InstantiationAwareBeanPostProcessor
,实例化Bean后,调用该接口的postProcessAfterInstantiation()
方法,可在这里对已经实例化的Bean进行一些"梳妆打扮" -
如果Bean配置了属性信息,那么容器会将配置值设置到对应的属性中,不过在设置每个属性之前会调用
postProcessPropertyValues()
方法。 -
调用bean 的属性设置方法设置属性
-
如果Bean实现了
BeanNameAwae
接口,将调用setBeanName()
接口方法,将配置文件该Bean对应的名称设置到bean中 -
如果Bean实现了
BeanFactoryAware
接口,将调用setBeanFactory()
接口方法,将BeanFactory容器实例设置到Bean中。 -
如果BeanFactory装配了
BeanPostProcessor
后处理器,将调用BeanPostProcessor
的postProcessBeforeInitialization(Object bean,String beanName)
接口方法对bean进行加工操作,其中入参是当前正在处理的bean,而beanName是当前Bean的配置名,返回的Bean为加工处理后的bean,用户可以会用该方法对某些Bean进行特殊处理,甚至改变Bean的行为。BeanPostProcessor
在Spring中占有重要的地位,为容器提供对Bean进行后续护理的切入点,Spring的AOP、动态代理都通过BeanPostProcessor
完成。 -
如果bean实现了
InitializingBean
接口,将调用接口的afterPropertiesSet()
方法。 -
如果在
<bean>
中通过init-method
属性定义了初始化方法,则执行这个方法。 -
BeanPostProcessor
中定义了两个方法,一个在第8步执行,另一个在这里执行postProcessAfterInitialization(Object bean, String beanName)
,容器再次获得对bean进行加工处理的机会。 -
如果
<bean>
中指定bean的作用范围为scope=“prototype”,则将Bean返回给调用者,调用者负责bean后续生命的管理,Spring不再管理这个Bean生命周期。如果将scope=“Singleton”,则将bean放入SpringIOC容器的缓存池中,并将bean引用返回给调用者,Spring继续对这些Bean进行管理。 -
对于scope=“Singleton”,当容器关闭时,将处罚Spring对bean后续生命周期的管理工作,如果Bean实现了
DisposableBean
接口,将调用接口的destroy()
方法。可以在此编写释放资源,记录日志等。 -
对于scope=“Singleton”,如果在
<bean>
中通过destory-method
属性定义销毁化方法,则执行这个方法。
3、ApplicationContext中bean的生命周期
1、Bean在ApplicationContext
中的生命周期和在BeanFactory
中的生命周期类似,不同的是如果Bean实现了ApplicationContextAware
接口,会增加一个接口方法setApplicationContext()
public class Car implements ApplicationContextAware, BeanNameAware,
InitializingBean, DisposableBean {
//属性
private ApplicationContext applicationContext;
//1、新增的ApplicationContext接口方法:setApplicationContext()
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
....重复方法和属性省略.......
}
2、如果在配置文件中声明了工厂后处理接口BeanFactoryPostProcessor
的实现类,则应用上下文在装配配置文件之后、初始化Bean实例之前将调用这些BeanFactoryPostProcessor
对配置信息进行加工处理。工厂后处理器是容器级的,仅在应用上下文初始化时调用一次,其目的地完成一一些配置文件的加工处理工作。更改配置信息。
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("car");
beanDefinition.getPropertyValues().addPropertyValue("brand","奇瑞QQ");
System.out.println("调用BeanFactoryPostProcessor.postProcessBeanFactory()!");
}
}
3、ApplicationContext
与BeanFactory
另一个最大的不同之处在于:前者会利用j反射机制自动识别出配置文件中定义的BeanFactoryPostProcessor
、InstantiationAwareBeanPostProcessor
、BeanPostProcessor
而后者需要在代码中手工调用addBeanPostProcessor()
方法进行注册。
<bean id="car" class="com.hh.bean.Car" init-method="myInit" destroy-method="myDestory">
<property name="brand" value="红旗CA72"/>
<property name="maxSpeed" value="200"/>
</bean>
<!--配置工厂后处理器-->
<bean id="myBeanPostProcessor" class="com.hh.beanfactory.MyBeanPostProcessor"/>
<!--注册Bean后处理器-->
<bean id="myBeanFactoryPostProcessor" class="com.hh.beanfactory.MyBeanFactoryPostProcessor"/>
<!--注册Bean后处理器-->
<bean id="myInstantiationAwareBeanPostProcessor" class="com.hh.beanfactory.MyInstantiationAwareBeanPostProcessor"/>
<!--
说明:这种不是自己写的类,jar包中的类如果想放入容器又不使用配置文件,
需要使用配置类:@Configuration+@Bean
-->
4、ApplicationContext
在启动时首先为配置文件中的每个<bean>
生成一个BeanDefinition
对象,BeanDefinition
是<bean>
在Spring中的内部表示,当配置文件中的所有<bean>
被解析成BeanDefinition
后,ApplicationContext
将调用工厂后处理器的方法,因此有机会通过程序的方式,调整Bean的配置信息。
public class BeanLifeCycle {
public static void main(String[] args) {
LifeCycleInBeanFactory();
}
public static void LifeCycleInBeanFactory(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//第一次从容器中获取car,将触发容器初始化Bean,将引发Bean生命周期方法的调用
Car car1 = (Car) context.getBean("car");
car1.introtuce();
car1.setColor("红色");
//第二次从容器中获取Car,直接从缓存池中获取
Car car2 = (Car)context.getBean("car");
System.out.println("car1==car2:"+ (car1==car2));
}
}
结果:
调用BeanFactoryPostProcessor.postProcessBeanFactory()!
调用MyInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
调用Car()的构造函数
调用MyInstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
调用MyInstantiationAwareBeanPostProcessor.postProcessPropertyValues()
调用setBrand()方法
调用BeanNameAware.setBeanName()。
调用MyBeanPostProcessor.postProcessBeforeInitialization() ,color为空,设置为黑色
调用InitializingBean.afterPropertiesSet()。
调用init-method所指定的myInit(),将maxSpeed设置为240
调用MyBeanPostProcessor.postProcessAfterInitialization() ,将maxSpeed调整为200
brand:奇瑞QQ;color:'黑色;maxSpeed:200
car1==car2:true