spring BeanFactory及ApplicationContext中Bean的生命周期

spring bean 的生命周期

spring BeanFactory及ApplicationContext在读取配置文件后、实例化bean前后、设置bean的属性前后这些点都可以通过实现接口添加我们自己的逻辑


spring BeanFactory中Bean的生命周期

demo1 

  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>4.3.16.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>4.3.16.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>4.3.16.RELEASE</version>
    </dependency>
  </dependencies>
pom.xml
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;

/**
 * BeanFactoryAware 觉察到
 * InitializingBean 初始化
 * Disposable 一次性的,可任意处理的; 用后就抛弃的
 *
 * BeanFactoryAware、BeanNameAware、InitializingBean、DisposableBean都是Bean级的生命周期控制接口
 */
public class Car implements BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean {
    // 品牌
    private String brand;
    // 颜色
    private String color;
    // 最快速度
    private int maxSpeed;

    public Car() {
        System.out.println("构造方法执行");
    }

    public void setBrand(String brand) {
        System.out.println("setBrand方法执行");
        this.brand = brand;
    }
    public String getColor() {
        return this.color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public int getMaxSpeed() {
        return maxSpeed;
    }

    public void setMaxSpeed(int maxSpeed) {
        this.maxSpeed = maxSpeed;
    }

    public void introduce() {
        System.out.println("brand:" + brand + ";color:" + color + ";maxSpeed:" + maxSpeed);
    }

    private BeanFactory beanFactory;
    @Override
    // 实现BeanFactoryAware需要重写的唯一方法
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("调用BeanFactoryAware接口定义的setBeanFactory方法");
        this.beanFactory = beanFactory;
    }

    private String beanName;
    @Override
    // 实现BeanNameAware需要重写的唯一方法
    public void setBeanName(String beanName) {
        System.out.println("调用BeanNameAware接口定义的setBeanName方法");
        this.beanName = beanName;
    }

    @Override
    // 实现InitializingBean需要重写的唯一方法
    public void afterPropertiesSet() throws Exception {
        System.out.println("调用InitializingBean接口定义的afterPropertiesSet方法");
    }

    @Override
    // 实现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方法");
    }
}
Car.java
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 {
    /**
     * 在实例化Bean前调用,仅对容器中的car Bean处理
     *
     * 父类实现了接口 SmartInstantiationAwareBeanPostProcessor,
     * SmartInstantiationAwareBeanPostProcessor 又继承了接口 InstantiationAwareBeanPostProcessor
     * InstantiationAwareBeanPostProcessor 又继承了 BeanPostProcessor
     * 有方法postProcessBeforeInstantiation
     */
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if ("car".equals(beanName)) {
            System.out.println("InstantiationAwareBeanPostProcessor 接口的 postProcessBeforeInstantiation 方法执行");
        }
        return null;
    }

    /**
     * 在实例化Bean后调用,仅对容器中的car Bean处理
     *
     * 同上,InstantiationAwareBeanPostProcessor 有方法 postProcessAfterInstantiation
     */
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if ("car".equals(beanName)) {
            System.out.println("InstantiationAwareBeanPostProcessor 接口的 postProcessAfterInstantiation 方法执行");
        }
        return true;
    }

    /**
     * 在设置某个属性时调用,仅对car Bean的品牌属性值进行处理,还可以通过pds入参进行过滤
     *
     * 同上,InstantiationAwareBeanPostProcessor 有方法 postProcessPropertyValues
     */
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
        if ("car".equals(beanName)) {
            System.out.println("InstantiationAwareBeanPostProcessor 接口的 postProcessPropertyValues 方法执行");
        }
        return pvs;
    }
}
MyInstantiationAwareBeanPostProcessor
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

/**
 * processor 加工,处理
 * BeanPostProcessor后处理器在spring框架中占有重要的地位,这是容器对Bean进行后续加工处理的切入点;
 * spring提供的动态代理、AOP都是通过BeanPostProcessor实现的
 */
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("调用接口BeanPostProcessor的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("调用接口BeanPostProcessor的postProcessAfterInitialization方法," +
                        "将maxSpeed调整为200");
                car.setMaxSpeed(200);
            }
        }
        return bean;
    }
}
MyBeanPostProcessor
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
      http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="car" class="Car" init-method="myInit" destroy-method="myDestroy"
    p:brand="宝马373" p:maxSpeed="220"/>

</beans>
my.xml
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.ClassPathResource;

/**
 * 测试类
 */
public class BeanLifeCycle {

    public static void main(String[] args) {
        lifeCycleBeanFactory();
    }

    private static void lifeCycleBeanFactory() {
        // 装载配置文件
        ClassPathResource resource = new ClassPathResource("my.xml");

        // 启动容器
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader((DefaultListableBeanFactory) beanFactory);
        reader.loadBeanDefinitions(resource);

        // 向容器中注册MyBeanPostProcessor后处理器
        ((ConfigurableBeanFactory)beanFactory).addBeanPostProcessor(new MyBeanPostProcessor());
        // 向容器中注册MyInstantiationAwareBeanPostProcessor后处理器
        ((ConfigurableBeanFactory)beanFactory).addBeanPostProcessor(new MyInstantiationAwareBeanPostProcessor());

        // 第一次从容器中获取car,将触发容器实例化这个Bean,这将引发Bean生命周期方法的调用
        Car car1 = (Car)beanFactory.getBean("car");
        car1.introduce();
        car1.setColor("红色");

        // 第二次从容器中获取car,直接从缓存池中获取
        Car car2 = (Car) beanFactory.getBean("car");

        // 查看car1和car2是否指向同一引用
        System.out.println("car1==car2:" + (car1 == car2));

        ((DefaultListableBeanFactory)beanFactory).destroySingletons();
    }
}
测试类
1、InstantiationAwareBeanPostProcessor 接口的 postProcessBeforeInstantiation 方法执行
构造方法执行
2、InstantiationAwareBeanPostProcessor 接口的 postProcessAfterInstantiation 方法执行
3、InstantiationAwareBeanPostProcessor 接口的 postProcessPropertyValues 方法执行
setBrand方法执行
4、调用BeanNameAware接口定义的setBeanName方法
5、调用BeanFactoryAware接口定义的setBeanFactory方法
6、调用接口BeanPostProcessor的postProcessBeforeInitialization方法,color为空,设置为默认黑色
7、调用InitializingBean接口定义的afterPropertiesSet方法
8、调用init-method指定的myInit方法,将maxSpeed设置为240
9、调用接口BeanPostProcessor的postProcessAfterInitialization方法,将maxSpeed调整为200
brand:宝马373;color:黑色;maxSpeed:200
car1==car2:true
10、调用DisposableBean接口定义的destroy方法
11、调用destroy-method指定的myDestroy方法

输出分析:
在一个bean实例化之间之后,调用1、2。
1的方法入参是Class<?> beanClass, String beanName,分别对应bean的class和id
2的方法入参是Object bean, String beanName,分别对应实例化好的bean和bean的id

在属性填充前,调用3。
3的方法入参是PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName
pvs里封装着属性值,pds里封装着属性名,bean是实例化后的bean,beanName是bean的id

属性填充后,调用4、5。
4的方法入参是String beanName,可以把beanName也就是bean的id缓存起来,保存为一个成员变量
5的方法入参是BeanFactory beanFactory,可以把beanFactory缓存起来,保存为一个成员变量

在bean初始化之前之后调用6、9,这是BeanPostProcessor的方法,可以修改属性值,可以添加AOP
7、8是初始化方法
10、11是销毁方法
运行输出分析

其中的BeanPostProcessor接口非常重要,spring的动态代理、AOP都是通过实现这个接口而为bean添加行为的


spring ApplicationContext中Bean的生命周期

Spring Bean在ApplicationContext和BeanFactory中的生命周期类似。

不同的是,如果Bean实现了org.springframework.context.ApplicationContextAware接口,会增加一个调用该接口方法setApplicationContext()的步骤。

并且多了BeanFactoryPostProcessor接口,如果实现了该接口,ApplicationContext在装载配置文件之后、实例化Bean之前将调用该实现类的方法,对配置信息进行加工处理。Spring框架提供了多个工厂后处理器,如CustomEditorConfigurer、PopertyPlaceholderConfigurer等。工厂后处理器是容器级的,仅在ApplicationContext初始化时调用一次。

ApplicationContext在启动时,将首先为配置文件中的每个<bean>生成一个BeanDefinition对象,BeanDefinition是<bean>在Spring容器中的内部表示。当配置文件中所有的<bean>都被解析为BeanDefinition时,ApplicationContext将调用工厂后处理器的方法,因些,我们有机会通过程序的方式调整Bean的配置信息。

ApplicationContext和BeanFactory的一个最大的不同之处在于,前者会利用Java反射机制自动识别出配置文件中定义的BeanPostProcessor、InstantiationAwareBeanPostProcessor及BeanFactoryPostProcessor,并自动将它们注册到ApplicatContext中(在ApplicatContext中,只需在配置文件中通过<bean>定义工厂后处理器和Bean后处理器,它们就会按预期的方式运行);而后者需要在代码中手工调用addBeanProcessor()方法进行注册。

demo2——BeanFactoryPostProcessor
还使用demo1那个例子的代码,添加了MyBeanFactoryPostProcessor的实现、修改了my.xml、修改了测试类 

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;

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    // 实现BeanFactoryPostProcessor需要重写的唯一方法
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        BeanDefinition beanDefinition = beanFactory.getBeanDefinition("car");
        beanDefinition.getPropertyValues().addPropertyValue("brand", "吉利博瑞");
        System.out.println("调用BeanFactoryPostProcessor的postProcessBeanFactory方法");
    }
}
MyBeanFactoryPostProcessor 
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
      http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="car" class="Car" init-method="myInit" destroy-method="myDestroy"
    p:brand="宝马373" p:maxSpeed="220"/>

    <bean class="MyBeanPostProcessor"/>

    <bean class="MyInstantiationAwareBeanPostProcessor"/>

    <bean class="MyBeanFactoryPostProcessor"/>

</beans>
my.xml 
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 测试类
 */
public class BeanLifeCycle {

    public static void main(String[] args) {
        lifeCycleBeanFactory();
    }

    private static void lifeCycleBeanFactory() {
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:my.xml");

        Car car1 = (Car)context.getBean("car");
        car1.introduce();
        car1.setColor("红色");

        // 第二次从容器中获取car,直接从缓存池中获取
        Car car2 = (Car) context.getBean("car");

        // 查看car1和car2是否指向同一引用
        System.out.println("car1==car2:" + (car1 == car2));

        ((ClassPathXmlApplicationContext)context).destroy();
    }
}
测试类

demo3——BeanFactoryPostProcessor
通过程序的方式调整Bean的配置信息

      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>4.3.16.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.3.16.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>4.3.16.RELEASE</version>
      </dependency>
pom.xml
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Driver {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("my.xml");
        Boss boss1 = context.getBean("boss1", Boss.class);
        Boss boss2 = context.getBean("boss2", Boss.class);

        System.out.println(boss1);
        System.out.println(boss2);
    }
}
class Boss {
    private Car car;

    public Car getCar() {
        return car;
    }

    public void setCar(Car car) {
        this.car = car;
    }
}
class Car { }
View Code
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;

/**
 * BeanPostProcessor
 * Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
 * Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
 *
 * BeanFactoryPostProcessor
 * void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
 *
 * BeanPostProcessor和BeanFactoryPostProcessor是两个不同的接口:
 * BeanPostProcessor是在Bean实例化后、属性设置后执行,是Spring AOP 的赖以实现的基础;
 * BeanFactoryPostProcessor是WebApplicationContext读取配置文件后,还没有初始化任何实例时运行,
 * 可以用来修改配置文件
 *
 */
public class UserServiceFactoryBean implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory bf) throws BeansException {
        // 把ConfigurableListableBeanFactory转化为DefaultListableBeanFactory
        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) bf;
        // 通过BeanDefinitionBuilder创建bean定义
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(Boss.class);
        // 设置属性userDao,此属性引用已经定义的bean:car
        beanDefinitionBuilder.addPropertyReference("car", "car");
        // 注册bean定义
        beanFactory.registerBeanDefinition("boss1", beanDefinitionBuilder.getRawBeanDefinition());
        // 直接注册一个bean实例
        beanFactory.registerSingleton("boss2", new Boss());
    }
}
View Code
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
      http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="car" class="Car"/>

    <bean class="UserServiceFactoryBean"/>

</beans>
View Code

 

posted @ 2019-01-14 15:05  zhuangrunwei  阅读(304)  评论(0编辑  收藏  举报