Bean的后置处理器

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

  • 调用顺序:在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的后置处理器》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

Computational Geometry

Computational Geometry

Mark de Berg、Otfried Cheong、Marc van Kreveld、Mark Overmars / Springer / 2008-4-16 / USD 49.95

This well-accepted introduction to computational geometry is a textbook for high-level undergraduate and low-level graduate courses. The focus is on algorithms and hence the book is well suited for st......一起来看看 《Computational Geometry》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

MD5 加密
MD5 加密

MD5 加密工具

SHA 加密
SHA 加密

SHA 加密工具