Bean的后置处理器

栏目: 后端 · 发布时间: 5年前

  • 调用顺序:在Bean的初始化前后调用,分别对应了其中的两个方法
  • Bean的后置处理器对应的接口是 BeanPostProcessor ,其中定义了两个方法,如下:
    public interface BeanPostProcessor{
    
    	/**
    	 * 在Bean初始化之前执行,即是在执行Bean的构造方法之后,在执行InitializingBean的afterPropertiesSet方法之前执行
    	 */
    	ObjectpostProcessBeforeInitialization(Object bean, String beanName)throws BeansException;
    
    	/**
             * 在Bean的初始化之后执行,即是在InitializingBean的afterPropertiesSet方法之后执行
    	 */
    	ObjectpostProcessAfterInitialization(Object bean, String beanName)throws BeansException;
    }
    

使用场景

  • 在Bean的初始化前后做一些自己的逻辑处理,比如为Bean设置一些额外的属性。
    • 最典型的例子就是spring中的Aware接口的实现,都是利用 BeanPostProcessor 在Bean初始化之前进行调用set方法设置相应的属性【详情请看 ApplicationContextAwareProcessor 源码】
    • @Autowired 的实现依赖注入也是使用的BeanPostProcessor的原理,详情请看 AutowiredAnnotationBeanPostProcessor 的源码

自定义后置处理器

  • 必备条件:
    BeanPostProcessor
    
  • 自定义一个User类,如下:

    /**
     * 实现InitializingBean接口,定义初始化方法,在构造方法之后执行
     */
    @Component
    public class Userimplements Serializable,InitializingBean{
        private String name;
    
        private Integer age;
    
        public User(){}
    
        public User(String name, Integer age){
            System.out.println("执行构造方法");
            this.name = name;
            this.age = age;
        }
        @Override
        public void afterPropertiesSet()throws Exception {
            System.out.println("执行初始化方法,在构造方法执行之后执行");
        }
    }
    
  • 自定义后置处理器,如下:

    /**
     * 1、自定义的后置处理器,实现BeanPostProcessor
     * 2、必须注入到容器中才能执行
     * 3、后置处理器是每一个Bean实例化前后都会调用的,并不能指定某一个
     */
    @Component
    public class FirstPostProcessorimplements BeanPostProcessor{
        /**
         * 在Bean初始化之前执行,即是在执行Bean的构造方法之后,在执行InitializingBean的afterPropertiesSet方法之前执行
         * @param bean bean的对象
         * @param beanName bean的名字,即是在ioc容器中的id
         * @return 一定不能null
         * @throws BeansException
         */
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName)throws BeansException {
            //如果这个Bean是User类型
            if (bean instanceof User){
                System.out.println("在User的初始化方法【afterPropertiesSet】之前执行");
                //改变属性的值
                User user=(User)bean;
                user.setName("马云");
                user.setAge(40);
            }
            return bean;
        }
    
        /**
         * 在Bean的初始化之后执行,即是在InitializingBean的afterPropertiesSet方法之后执行
         * @param bean bean的对象
         * @param beanName bean的名字,即是在ioc容器中的id
         * @return 一定不能null
         * @throws BeansException
         */
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName)throws BeansException {
            if (bean instanceof User){
                System.out.println("在User的初始化方法【afterPropertiesSet】之后执行");
            }
            return bean;
        }
    }
    

源码解析

  • 最重要的就是后置处理器两个方法的执行顺序:
    postProcessBeforeInitialization
    postProcessAfterInitialization
    
  • 我们分别在自定义的后置处理器上打上断点,通过debug模式跟踪代码,程序的入口测试类如下:
    • 使用 AnnotationConfigApplicationContext 启动容器
      public class FirstConfigTest{
          public AnnotationConfigApplicationContext applicationContext;
      
          @Before
          public void initApplicationContext(){
              applicationContext = new AnnotationConfigApplicationContext(FirstConfig.class);
          }
      }
      

步骤

  1. 执行AnnotationConfigApplicationContext的构造方法 public AnnotationConfigApplicationContext(Class<?>... annotatedClasses)
    1. register(annotatedClasses) :注入指定的配置类 FirstConfig
    2. refresh() :刷新容器,在这个执行结束之后会完成Bean的加载,详情见第2步】
  2. 进入 org.springframework.context.support.AbstractApplicationContext#refresh 方法:
    1. prepareRefresh(); :在刷新容器之前做一些准备工作,比如设置激活状态【activate】,设置启动时间【startupDate】
    2. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
      refreshBeanFactory()
      ConfigurableListableBeanFactory
      
    3. prepareBeanFactory(beanFactory); :对新创建的Bean工厂设置一些属性配置
      1. 设置ClassLoader、表达式解析器、属性注入器
      2. 设置 ApplicationContextAwareProcessor 这个后置处理器到 org.springframework.beans.factory.support.AbstractBeanFactory#beanPostProcessors 该成员变量中、去除一些不能自动注入的类【ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware、EnvironmentAware】,因为这些Aware类型的类需要后续自定义实现的
      3. 向容器中注入一些能够自动注入的类【BeanFactory,ResourceLoader,ApplicationEventPublisher,ApplicationContext】,这些类能够直接通过 @Autowired 直接注入使用
      4. 向容器中注入一些运行环境的Bean【 ConfigurableEnvironmentsystemProperties(Map<String,Object> 其中存放的是配置参数)】,这些Bean可以直接自动注入使用
    4. invokeBeanFactoryPostProcessors(beanFactory) :调用已经注册在容器中的BeanFactory后置处理器
    5. registerBeanPostProcessors(beanFactory) :向ioc容器中注册BeanFactoryProcessor
    6. initMessageSource() :初始化MessageSource
    7. initApplicationEventMulticaster() :初始化事件分发器
    8. registerListeners() :注册事件监听器,用来监听事件
    9. finishBeanFactoryInitialization(beanFactory) :初始化单例、非懒加载的Bean】,详情见步骤3
    10. finishRefresh() :发布事件
  3. 进入 org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization :
    1. 初始化类型转换类
    2. 初始化 LoadTimeWeaverAware ,用于方法织入
    3. 冻结BeanDefinition,表示后面的BeanDefinition不能再改变
    4. beanFactory.preInstantiateSingletons() :初始化Bean,详情请看第4步】
  4. 进入到 org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons 方法中,用于初始化Bean

    1. 遍历所有的BeanNames,判断当前Bean是否是FactoryBean,如果不是运行getBean方法
  5. 进入到 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean ,如下图所示,将是完整的逻辑,可以看出后置处理器为什么是在初始化之前和之后执行。

    1. Bean的后置处理器

总结

  • 从源码可以看出,最核心的执行就是在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean 的方法中,主要的代码逻辑是在初始化之前调用对应的before方法,在之后调用after方法。

以上所述就是小编给大家介绍的《Bean的后置处理器》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

产品增长力

产品增长力

李阳 / 机械工业出版社 / 2018-4-1 / 59

本书由京东资深数据产品经理撰写,重新定义了数据与产品、业务的关系,从数据分析方法、数据价值挖掘、数据结果倒逼业务优化3个层次,以及设计、运营和优化3个维度,为产品增长提供了科学的依据和方法论,得到了PMCaff创始人阿德、GrowingIO创始人&CEO张溪梦、增长官研究院创始人范冰、腾讯高级产品经理刘涵宇等专家的高度评价。 全书内容以理论为主线,以实操为目标,萃取技术实操与管理思维中的精华......一起来看看 《产品增长力》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具