美文网首页
spring bean的生命周期

spring bean的生命周期

作者: zhengaoly | 来源:发表于2022-03-03 09:57 被阅读0次

    spring bean的生命周期

    原创基础上修改,建议参考

    Spring 作为当前 Java 最流行、最强大的轻量级框架,受到了程序员的热烈欢迎。准确的了解 Spring Bean 的生命周期是非常必要的。我们通常使用 ApplicationContext 作为 Spring 容器。这里,我们讲的也是 ApplicationContext 中 Bean 的生命周期。而实际上 BeanFactory 也是差不多的,只不过处理器需要手动注册。

    转载请注明地址 http://www.cnblogs.com/zrtqsk/p/3735273.html

    一、生命周期流程图:

    Spring Bean 的完整生命周期从创建 Spring 容器开始,直到最终 Spring 容器销毁 Bean,这其中包含了一系列关键点。

    img img

    若容器注册了以上各种接口,程序那么将会按照以上的流程进行。下面将仔细讲解各接口作用。

    二、各种接口方法分类

    Bean 的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:

    1、Bean 自身的方法  :  这个包括了 Bean 本身调用的方法和通过配置文件中 <bean> 的 init-method 和 destroy-method 指定的方法

    2、Bean 级生命周期接口方法  :  这个包括了 BeanNameAware、BeanFactoryAware、InitializingBean 和 DiposableBean 这些接口的方法

    3、容器级生命周期接口方法  :  这个包括了 InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为 “后处理器”。

    4、工厂后处理器接口方法  :  这个包括了 AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer 等等非常有用的工厂后处理器  接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。这些处理器一般处理beandifinition,因为此时bean还没有实例化.

    三、演示

    我们用一个简单的 Spring Bean 来演示一下 Spring Bean 的生命周期。

    1、首先是一个简单的 Spring Bean,调用 Bean 自身的方法和 Bean 级生命周期接口方法,为了方便演示,它实现了 BeanNameAware、BeanFactoryAware、InitializingBean 和 DiposableBean 这 4 个接口,同时有 2 个方法,对应配置文件中@Bean的 init-method 和 destroy-method。如下:

    package com.hisense.smartstation.beantest;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.*;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    
    import java.io.Serializable;
    
    /**
     * @ClassName: Student
     * @Description: TODO
     * @Create by: gaozhen
     * @Date: 2022/3/3 15:49
     */
    @ConfigurationProperties(prefix = "stu")
    public class Student implements Serializable, InitializingBean, DisposableBean, BeanFactoryAware, BeanNameAware {
        public Student() {
            System.out.println("Student.constructor");
        }
        @Autowired
        BirthDay birthDay;
    
        private String name;
        private String sex;
        private int age;
        public void init(){
            System.out.println("Student.init");
        }
    
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("InitializingBean.afterPropertiesSet");
        }
    
        @Override
        public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
            System.out.println("BeanFactoryAware.setBeanFactory");
        }
    
        @Override
        public void setBeanName(String name) {
            System.out.println("BeanNameAware.setBeanName");
        }
    
        @Override
        public void destroy() throws Exception {
            System.out.println("DisposableBean.destroy");
        }
    
        public String getName() {
            System.out.println("Student.getName");
            return name;
        }
    
        public void setName(String name) {
            System.out.println("Student.setName");
            this.name = name;
        }
    
        public String getSex() {
            return sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    }
    
    

    2、接下来是演示 BeanPostProcessor 接口的方法,如下:

    package com.hisense.smartstation.beantest;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    import org.springframework.stereotype.Component;
    
    /**
     * @ClassName: StudentBeanPostProcessor
     * @Description: 初始化前后
     * @Create by: gaozhen
     * @Date: 2022/3/2 9:24
     */
    @Component
    public class StudentBeanPostProcessor implements BeanPostProcessor {
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            if (bean instanceof Student){
                System.out.println("BeanPostProcessor.postProcessBeforeInitialization");
            }
            return bean;
        }
    
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            if (bean instanceof Student) {
                System.out.println("BeanPostProcessor.postProcessAfterInitialization");
            }
            return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
        }
    }
    
    

    如上,BeanPostProcessor 接口包括 2 个方法 postProcessAfterInitialization 和 postProcessBeforeInitialization,这两个方法的第一个参数都是要处理的 Bean 对象,第二个参数都是 Bean 的 name。返回值也都是要处理的 Bean 对象。这里要注意。

    3、InstantiationAwareBeanPostProcessor 接口本质是 BeanPostProcessor 的子接口,一般我们继承 Spring 为其提供的适配器类 InstantiationAwareBeanPostProcessor Adapter 来使用它,如下:

    package com.hisense.smartstation.beantest;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.PropertyValues;
    import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
    import org.springframework.stereotype.Component;
    
    /**
     * @ClassName: StudentInstantiationBeanPostProcessor
     * @Description: InstantiationAwareBeanPostProcessorAdapter实现了InstantiationAwareBeanPostProcessor
     * 用来进行bean实例化前,后,属性注入等工作。
     * @Create by: gaozhen
     * @Date: 2022/3/3 10:37
     */
    @Component
    public class StudentInstantiationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
        /**
         * bean实例化之前调用
         * @param beanClass
         * @param beanName
         * @return
         * @throws BeansException
         */
        @Override
        public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
            if (beanClass.equals(Student.class)) {
                System.out.println("InstantiationBeanPostProcessor.BeforeInstantiation()");
            }
            return super.postProcessBeforeInstantiation(beanClass, beanName);
        }
    
        /**
         * bean实例化以后调用
         * @param bean
         * @param beanName
         * @return
         * @throws BeansException
         */
        @Override
        public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
            if (bean.getClass().equals(Student.class)) {
                System.out.println("InstantiationBeanPostProcessor.AfterInstantiation()");
            }
            return super.postProcessAfterInstantiation(bean, beanName);
        }
    
        /**
         * 此处可以进行依赖注入等,@autowired,@resource等注解,都是通过调用此方法进行的依赖注入
         * 相关参考:
         * @autowired使用AutowiredAnnotationBeanPostProcessor#postProcessProperties()方法
         * @resource使用CommonAnnotationBeanPostProcessor#postProcessProperties()方法
         * CommonAnnotationBeanPostProcessor进行注入,他们都是实现了InstantiationAwareBeanPostProcessor接口
         * @param pvs
         * @param bean
         * @param beanName
         * @return
         * @throws BeansException
         */
        @Override
        public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
            if (bean.getClass()== Student.class) {
                System.out.println("InstantiationBeanPostProcessor.processProperties()");
            }
    
            return super.postProcessProperties(pvs, bean, beanName);
        }
    
        /**
         * 初始化前
         * @param bean
         * @param beanName
         * @return
         * @throws BeansException
         */
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            if (bean.getClass().equals(Student.class)) {
                System.out.println("InstantiationBeanPostProcessor.BeforeInitialization()");
            }
            return super.postProcessBeforeInitialization(bean, beanName);
        }
    
        /**
         * 初始化后
         * @param bean
         * @param beanName
         * @return
         * @throws BeansException
         */
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            if (bean.getClass().equals(Student.class)) {
                System.out.println("InstantiationBeanPostProcessor.AfterInitialization()");
            }
            return super.postProcessAfterInitialization(bean, beanName);
        }
    }
    
    

    这个有 3 个方法,其中第二个方法 postProcessAfterInitialization 就是重写了 BeanPostProcessor 的方法。第三个方法 postProcessPropertyValues 用来操作属性,返回值也应该是 PropertyValues 对象。

    4、注入对象BirthDay

    package com.hisense.smartstation.beantest;
    
    import org.springframework.stereotype.Component;
    
    /**
     * @ClassName: BirthDay
     * @Description: TODO
     * @Create by: gaozhen
     * @Date: 2022/3/3 14:16
     */
    @Component
    public class BirthDay {
        String birth = "20220303";
    }
    
    

    这里添加一个被注入的对象给Student,主要是为了查看BirthDay这个bean是何时被注入的,参考AutowiredAnnotationBeanPostProcessor#postProcessProperties()方法,是在Student的bean实例化以后,通过AutowiredAnnotationBeanPostProcessor#postProcessProperties()注入的,此处可添加条件断点查看.

    image-20220303162602676

    5、工厂后处理器接口方法BeanFactoryPostProcessor,如下:

     1 package springBeanTest;
     2 
     3 import org.springframework.beans.BeansException;
     4 import org.springframework.beans.factory.config.BeanDefinition;
     5 import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
     6 import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
     7 
     8 public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
     9 
    10     public MyBeanFactoryPostProcessor() {
    11         super();
    12         System.out.println("这是BeanFactoryPostProcessor实现类构造器!!");
    13     }
    14 
    15     @Override
    16     public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0)
    17             throws BeansException {
    18         System.out
    19                 .println("BeanFactoryPostProcessor调用postProcessBeanFactory方法");
    20         BeanDefinition bd = arg0.getBeanDefinition("person");
    21         bd.getPropertyValues().addPropertyValue("phone", "110");
    22     }
    23 
    24 }
    

    5、配置文件如下 beans.xml,很简单,使用 ApplicationContext, 处理器不用手动注册:

    package com.hisense.smartstation.beantest;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * @ClassName: StudentConfiguration
     * @Description: TODO
     * @Create by: gaozhen
     * @Date: 2022/3/3 15:56
     */
    @Configuration
    public class StudentConfiguration {
        @Bean(initMethod = "init",destroyMethod = "destroy")
        public Student getStudent(){
            return new Student();
        }
    }
    
    

    6、yml配置:

    stu:
      age: 20
      name: testuser
    

    执行结果

    bean factory post processor called
    InstantiationBeanPostProcessor.BeforeInstantiation()
    Student.constructor
    InstantiationBeanPostProcessor.AfterInstantiation()
    InstantiationBeanPostProcessor.processProperties()
    BeanNameAware.setBeanName
    BeanFactoryAware.setBeanFactory
    Student.setName
    BeanPostProcessor.postProcessBeforeInitialization
    InstantiationBeanPostProcessor.BeforeInitialization()
    InitializingBean.afterPropertiesSet
    Student.init
    BeanPostProcessor.postProcessAfterInitialization
    InstantiationBeanPostProcessor.AfterInitialization()
    
    image-20220303162528850 image.png

    相关文章

      网友评论

          本文标题:spring bean的生命周期

          本文链接:https://www.haomeiwen.com/subject/mnpyrrtx.html