美文网首页技术干货Spring源码分析spring
spring BeanPostProcessor 生命周期

spring BeanPostProcessor 生命周期

作者: BugPool | 来源:发表于2020-02-22 21:25 被阅读0次

    BeanPostProcessor:后置处理器
    spring使用模板模式,在bean的创建过程中安插了许多锚点,用户寻找对应的锚点,通过重写方法介入到bean的创建过程当中。本节通过重写这些锚点,学习如何使用BeanPostProcessor、获取各类BeanAware并且理清bean的生命周期

    代码

    控制台

    // 控制台的输出结果
    1. postProcessBeforeInstantiation被调用
    2. 构造方法被调用,name:小小
    3. postProcessAfterInstantiation被调用
    4. postProcessProperties被调用
    5. BeanNameAware被调用, 获取到的beanName:lifeCycleBean
    6. BeanFactoryAware被调用,获取到beanFactory:org.springframework.beans.factory.support.DefaultListableBeanFactory@117e949d: defining beans [lifeCycleBean,lifeCycleBeanPostProcessor]; root of factory hierarchy
    7. ApplicationContextAware被调用,获取到ApplicationContextAware:org.springframework.context.support.ClassPathXmlApplicationContext@71e9ddb4, started on Sat Feb 22 20:30:35 CST 2020
    8. postProcessBeforeInitialization被调用,把name改成中中
    9. afterPropertiesSet被调用
    10. myInit自定义初始化方法被调用,name:中中
    11. postProcessAfterInitialization被调用,把name改成大大
    12. bean创建完成 name: 大大
    13. DisposableBean被调用
    14. destroy-method自定义销毁方法被调用
    
    Process finished with exit code 0
    
    1. 创建类LifeCycleBean
    public class LifeCycleBean implements
            BeanNameAware,
            BeanFactoryAware,
            ApplicationContextAware,
            InitializingBean,
            DisposableBean {
    
        private BeanFactory beanFactory;
    
        private ApplicationContext applicationContext;
    
        private String name;
    
        public LifeCycleBean(String name) {
            System.out.println("2. 构造方法被调用,name:" + name);
            this.name = name;
        }
    
        @Override
        public void setBeanName(String name) {
            System.out.println("5. BeanNameAware被调用, 获取到的beanName:" + name);
        }
    
        @Override
        public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
            this.beanFactory = beanFactory;
            System.out.println("6. BeanFactoryAware被调用,获取到beanFactory:" + beanFactory);
        }
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            this.applicationContext = applicationContext;
            System.out.println("7. ApplicationContextAware被调用,获取到ApplicationContextAware:" + applicationContext);
        }
    
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("9. afterPropertiesSet被调用");
        }
    
        public void myInit() {
            System.out.println("10. myInit自定义初始化方法被调用,name:" + getName());
        }
    
        @Override
        public void destroy() throws Exception {
            System.out.println("13. DisposableBean被调用");
        }
    
        public void myDestroy() {
            System.out.println("14. destroy-method自定义销毁方法被调用");
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public BeanFactory getBeanFactory() {
            return beanFactory;
        }
    
        public ApplicationContext getApplicationContext() {
            return applicationContext;
        }
    }
    
    1. 创建BeanPostProcessor后置处理器(postProcessProperties过时了,这里就不演示了)
    public class LifeCycleBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    
        @Override
        public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
            if (beanName.equals("lifeCycleBean")) {
                System.out.println("1. postProcessBeforeInstantiation被调用");
            }
            return null;
        }
    
        @Override
        public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
            if (beanName.equals("lifeCycleBean")) {
                System.out.println("3. postProcessAfterInstantiation被调用");
            }
            return true;
        }
    
        @Override
        public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
            if (beanName.equals("lifeCycleBean")) {
                System.out.println("4. postProcessProperties被调用");
            }
            return null;
        }
    
    //  @Override
    //  public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
    //      return pvs;
    //  }
    
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            if (beanName.equals("lifeCycleBean")) {
                ((LifeCycleBean) bean).setName("中中");
                System.out.println("8. postProcessBeforeInitialization被调用,把name改成中中");
            }
            return bean;
        }
    
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            if (beanName.equals("lifeCycleBean")) {
                ((LifeCycleBean) bean).setName("大大");
                System.out.println("11. postProcessAfterInitialization被调用,把name改成大大");
            }
            return bean;
        }
    }
    
    1. xml配置文件
    <?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="lifeCycleBean" class="lifeCycle.LifeCycleBean"
              destroy-method="myDestroy"
              init-method="myInit">
            <constructor-arg value="小小"/>
        </bean>
    
        <bean id="lifeCycleBeanPostProcessor" class="lifeCycle.LifeCycleBeanPostProcessor"/>
    
    </beans>
    
    1. 测试类
    /**
     * @author: chaitou
     */
    public class LifeCycleTest {
    
        @Test
        public void test() {
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("lifeCycle.xml");
            LifeCycleBean myLifeCycleBean = applicationContext.getBean("lifeCycleBean", LifeCycleBean.class);
            System.out.println("12. bean创建完成 name: " + myLifeCycleBean.getName());
            ((ClassPathXmlApplicationContext) applicationContext).destroy();
        }
    }
    

    结果

    // 控制台的输出结果
    
    1. postProcessBeforeInstantiation被调用
    2. 构造方法被调用,name:小小
    3. postProcessAfterInstantiation被调用
    4. postProcessProperties被调用
    5. BeanNameAware被调用, 获取到的beanName:lifeCycleBean
    6. BeanFactoryAware被调用,获取到beanFactory:org.springframework.beans.factory.support.DefaultListableBeanFactory@117e949d: defining beans [lifeCycleBean,lifeCycleBeanPostProcessor]; root of factory hierarchy
    7. ApplicationContextAware被调用,获取到ApplicationContextAware:org.springframework.context.support.ClassPathXmlApplicationContext@71e9ddb4, started on Sat Feb 22 20:30:35 CST 2020
    8. postProcessBeforeInitialization被调用,把name改成中中
    9. afterPropertiesSet被调用
    10. myInit自定义初始化方法被调用,name:中中
    11. postProcessAfterInitialization被调用,把name改成大大
    12. bean创建完成 name: 大大
    13. DisposableBean被调用
    14. destroy-method自定义销毁方法被调用
    
    Process finished with exit code 0
    

    分析总结

    1. BeanPostProcess
      实例化相关:postProcessBeforeInstantiation、postProcessAfterInstantiation
      填充属性相关:postProcessProperties、postProcessPropertyValues(已过时没有演示)
      初始化相关:postProcessBeforeInitialization、postProcessAfterInitialization
      通过重写BeanPostProcess的方法,可以介入bean创建的不同环节。同时通过postProcessBeforeInitialization将bean的name属性值从小小改成了中中,又通过postProcessAfterInitialization将中中改成了大大,成功介入了bean的创建,并且依据我们的意愿修改了bean

    2. BeanNameAware、BeanFactoryAware、ApplicationContextAware
      这3类不属于后置处理器的范畴,学名叫感知器,让bean能感知到整个容器上下文信息的接口。spring在创建过程中,通过回调子类的setBeanName, setBeanFactory, setApplicationContext实现了BeanName, BeanFactory, ApplicationContext的注入,让bean能够感知获取到spring上下文的相关信息。虽然实现的东西很牛逼,但是实现的原理一点不复杂。通过检测当前的bean是否实现相关Aware,如果实现则调用子类set方法,将当前的BeanFactory等作为参数传入,直接上源码,看不懂可以参考这篇源码:spring源码日记17: 初始化

        private void invokeAwareMethods(final String beanName, final Object bean) {
            if (bean instanceof Aware) {
                if (bean instanceof BeanNameAware) {
                    ((BeanNameAware) bean).setBeanName(beanName);
                }
                if (bean instanceof BeanClassLoaderAware) {
                    ClassLoader bcl = getBeanClassLoader();
                    if (bcl != null) {
                        ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
                    }
                }
                if (bean instanceof BeanFactoryAware) {
                    ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
                }
            }
        }
    
    1. 最后贴出总结后的流程图


      spring创建Bean .jpg

    相关文章

      网友评论

        本文标题:spring BeanPostProcessor 生命周期

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