spring4.x(五)之第四章--Bean 的生命周期
程序员文章站
2024-03-18 08:54:28
...
1. BeanFactory 中 Bean 的生命周期
1. 对于 bean 的生命周期的分类
步骤详解:
注意:
2. Bean 生命周期实例
package com.smart;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
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 String getBrand() {
return brand;
}
public void setBrand(String brand) {
System.out.println("调用setBrand()设置属性");
this.brand = brand;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getMaxSpeed() {
return maxSpeed;
}
public void setMaxSpeed(int maxSpeed) {
this.maxSpeed = maxSpeed;
}
// BeanFactoryAware接口方法
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("调用BeanFactoryAware.setBeanFactory().");
this.beanFactory = beanFactory;
}
// BeanNameAware接口方法
public void setBeanName(String s) {
System.out.println("调用BeanNameAware.setBeanName().");
this.beanName = s;
}
// DisposableBean接口方法
public void destroy() throws Exception {
System.out.println("调用DisposableBean.destroy().");
}
// InitializingBean接口方法
public void afterPropertiesSet() throws Exception {
System.out.println("调用InitialingBean.afterPropertiesSet().");
}
// 通过<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().");
}
}
package com.smart.beanfactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import java.beans.PropertyDescriptor;
public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
@Override
// 1.接口方法,在实例化Bean前调用
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
// 1-1. 仅对容器中的car Bean进行处理
if ("car".equals(beanName)) {
System.out.println("调用InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation().");
}
return null;
}
@Override
// 2.接口方法,在实例化Bean后调用
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if ("car".equals(beanName)) {
System.out.println("调用InstantiationAwarePostProcessor.postProcessorAfterInstantiation().");
}
return true;
}
@Override
// 3.接口方法,在设置某个属性时调用
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
// 3-1. 仅对容器中的car Bean进行处理, 还可以同过pds入参进行过滤
if ("car".equals(beanName)) {
System.out.println("调用InstantiationAwarePostProcessor.postProcessPropertyValues().");
}
return pvs;
}
}
<?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.xsd">
<bean id="car" class="com.smart.Car"
init-method="myInit"
destroy-method="myDestroy"
p:brand="红旗CA72"
p:maxSpeed="200"/>
</beans>
package com.smart.beanfactory;
import com.smart.Car;
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.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
public class BeanLifeCycle {
public static void lifeCycleInBeanFactory() {
// 1. 装载配置文件并启动容器
Resource res = new ClassPathResource("beans.xml");
BeanFactory bf = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader((DefaultListableBeanFactory) bf);
reader.loadBeanDefinitions(res);
//后处理器的实际调用顺序与注册顺序无关,在具有多个后处理器的情况下,必须通过实现
//org.springframework.core.Ordered接口来确定调用顺序
// 2. 向容器中注册MyBeanPostProcessor后处理器
((ConfigurableBeanFactory) bf).addBeanPostProcessor(new MyBeanPostProcessor());
// 3. 向容器中注册MyInstantiationAwareBeanPostProcessor后处理器
((ConfigurableBeanFactory) bf).addBeanPostProcessor(new MyInstantiationAwareBeanPostProcessor());
// 4. 第一次从容器中获得car, 将触发容器实例化该Bean,这将引发Bean生命周期方法的调用
Car car1 = (Car) bf.getBean("car");
car1.introduce();
car1.setColor("红色");
// 5. 第二次从容器中获取car, 直接从缓存池中获取
Car car2 = (Car) bf.getBean("car");
// 6. 查看car1和car2是否指向同一引用
System.out.println("car1==car2: " + (car1 == car2));
// 7. 关闭容器
((DefaultListableBeanFactory) bf).destroySingleton("car");
}
public static void main(String[] args) {
lifeCycleInBeanFactory();
}
}
输出:
解析:
2. ApplicationContext 中 Bean 的生命周期
与BeanFactory类似,不同的是,如果Bean实现了org.springframework.context.ApplicationContextAware
接口,则会增加一个调用该接口方法setApplicationContext()
的步骤
ApplicationContext和BeanFactory另一个最大的不同在于:
- ApplicationContext会利用Java反射机制自动识别出配置文件中定义的BeanPostProcessor,InstantiationAwareBeanPostProcessor和BeanFactoryPostProcessor并自动将它们注册到context中
- BeanFactory需要在代码中通过调用addBeanPostProcessor()方法进行注册
在ApplicationContext中,只需在配置文件中通过定义工厂处理器和Bean后处理器,它们就会按预期的方式运行。
下面是使用工厂后处理器(BeanFactoryPostProcessor)的实例
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor{
//对car<bean>的brand属性配置信息进行加工操作
public void postProcessBeanFactory(ConfigurableListableBeanFactory bf)throws BeansException{
BeanDefinition bd=bf.getBeanDefinition("car");
bd.getPropertyValues().addPropertyValue("brand","特斯拉modelS");
System.out.println("调用BeanFactoryPostProcessor.postProcessBeanFactory");
}
}
ApplicationContext在启动时,将首先为配置文件中的每个<bean>
生成一个BeanDefination对象,它是<bean>
在Spring容器中的内部表示。当配置文件中所有的<bean>
都被解析成BeanDefinition时,ApplicationContext将调用BeanFactoryPostProcessor的方法,通过程序的方式调整Bean 的配置信息
<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">
<!-- 这个brand属性的值将被BeanFactoryPostProcessor更改掉-->
<bean id="car" class="com.smart.Car"
init-method="myInit"
destroy-method="myDestory"
p:color="黑色"
p:brand="红旗CA72"
p:maxSpeed="200"
/>
<!--注册Bean后处理器-->
<bean id="myBeanPostProcessor" class="com.smart.context.MyBeanPostProcessor"/>
<!-- 工厂后处理器-->
<bean id="myBeanFactoryPostProcessor" class="com.smart.context.MyBeanFactoryPostProcessor" />
</beans>