zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    iPhone6虽好,但也要借鉴这八个功能
    中小型企业商业智能平台的开发和实现(数据仓库、BI系统、真实项目实战)
    iOS开发入门教程_iOS开发视频教程
    零基础入门jQuery视频教程
    零基础3G Android移动开发就业培训
    请求库requesets库使用
    请求头加引号工具
    请求库urllib使用
    【Liunx】saltstack运维工具
    【Liunx】消息队列rabbitmp
  • 原文地址:https://www.cnblogs.com/Mike_Chang/p/10266844.html
Copyright © 2011-2022 走看看