Spring BeanFactoryPostProcessor and BeanPostProcessor

2022年4月18日 118点热度 0人点赞 0条评论

BeanFactoryPostProcessorBeanPostProcessor, 这两个接口都是 Spring 初始化 bean 时对外暴露的扩展点. 两个接口名称看起来很相似, 但作用及使用场景却不同.

BeanFactoryPostProcessor 接口

BeanFactoryPostProcessor 接口的定义如下:

public interface BeanFactoryPostProcessor {

    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

方法的注释翻译如下:

在应用上下文内部的 bean factory 初始化之后, 可以在这个接口中对其进行修改. 这个时候所有的 bean definition 都被加载了, 但是还没有任何 bean 被实例化. 所以我们可以在这个方法中对 bean 进行重写或者增加属性, 即使这个 bean 是即将被初始化的 (eager-initializing beans).

这个方法的参数是应用上下文所使用的的 beanFactory.

而这个 BeanFactoryPostProcessor 接口的注释翻译如下:

这个接口可以允许用户自定义应用上下文的 bean definition, 适配应用上下文底层的 bean factory 的 bean 属性值.
应用上下文可以自动检测它们的 bean definitions 中的 BeanFactoryPostProcessor beans, 并且在它们的任何 bean 创建之前可以应用这些设置.
这个接口对于系统管理员来自定义修改应用上下文中定义的 bean 属性非常方便.
可以参考 PropertyResourceConfigurer 和它的具体实现, 是如何解决这类配置需求的.
BeanFactoryPostProcessor 可能访问或者修改 bean definition, 但绝不会修改 bean 的实例. 如果修改 bean 实例的话可能会导致过早的 bean 的实例化, 会和容器冲突以及导致意想不到的副作用. 如果需要和 bean 实例交互的话, 可以考虑实现 BeanPostProcessor 这个接口.

本来我是没有搞清楚这两个接口有啥用的, 注释让我学明白了, 可以去装逼了.

这里贴一个我们项目中用到的 BeanFactoryPostProcessor 的用法:

@Component
public class MarkLazyInitBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // 判断是否启用 bean 的懒加载
        if (LazyInitUtils.isEnableLazy()) {
            // 获取 bean definition 的 name 数组
            String[] beanNames = beanFactory.getBeanDefinitionNames();
            for (String beanName : beanNames) {
                // 根据名称获取 bean definition
                BeanDefinition definition = beanFactory.getBeanDefinition(beanName);
                // 以 DaoImpl 结尾的, 并符合正则的标记为懒加载
                if (definition != null && definition.getBeanClassName() != null
                        && LazyInitUtils.isDaoImplement(definition.getBeanClassName())
                        && LazyInitUtils.isDaoImplBeanLazy(definition.getBeanClassName())) {
                    definition.setLazyInit(true);
                // 这里建议不要调用 getBean 来获取某个类的实例进行一些操作, 因为这里 get 的话, 它可能还没有进行属性赋值
                }
            }
        }
    }
}

注意上面的这个例子以一种简单的方式实现并注册这个接口: 加上@Component 注解, 使其加入到 Spring 容器中,Spring 会自动识别并在适当位置调用. 在 BeanFactoryPostProcessor 接口中不要调用 getBean 来获取某个类的实例进行一些操作, 因为这里 get 的话, bean 可能还没有进行属性赋值 (Spring 中关于接口的注释也有提到).

实现 BeanFactoryPostProcessor 接口, 可以在 spring 的 bean 创建之前, 修改 bean 的定义属性. 也就是说,Spring 允许 BeanFactoryPostProcessor 在容器实例化任何其它 bean 之前读取配置元数据, 并可以根据需要进行修改, 例如可以把 bean 的 scope 从 singleton 改为 prototype, 也可以把 property 的值给修改掉. 可以同时配置多个 BeanFactoryPostProcessor, 并通过设置 order 属性来控制各个 BeanFactoryPostProcessor 的执行次序.

注意:BeanFactoryPostProcessor 是在 spring 容器加载了 bean 的定义文件之后, 在 bean 实例化之前执行的. 接口方法的入参是 ConfigurrableListableBeanFactory, 使用该参数, 可以获取到相关 bean 的定义信息.

spring 中, 有内置的一些 BeanFactoryPostProcessor 实现类, 常用的有 (TODO 看下 Spring 是怎么使用的):

  • org.springframework.beans.factory.config.PropertyPlaceholderConfigurer
  • org.springframework.beans.factory.config.PropertyOverrideConfigurer
  • org.springframework.beans.factory.config.CustomEditorConfigurer

那么, BeanFactoryPostProcessor 的处理器是在哪儿调用的呢?

答案就是 AbstractApplicationContext 这个类的 refresh() 方法:

// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);

看看 invokeBeanFactoryPostProcessors 这个方法的具体实现:

/**
 * 实例化并且调用所有注册的 BeanFactoryPostProcessor beans,
 * 如果显示指定了 order 就按照 order 来执行.
 * 这个方法必须在单例的 bean 实例化之前执行.
 */
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

    // 特殊情况处理
    if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
}

整个 BeanFactoryPostProcessor 的调用实际上又委托给了 PostProcessorRegistrationDelegate 这个类.

BeanFactoryPostProcessor 使用场景

  • 配置文件的加密和解密
  • PropertyPlaceholderConfigurer 将配置文件中的属性读到 bean 中.
    BeanFactoryPostProcessor 的子类 PropertyPlaceholderConfigurer 可以在 bean 实例化之前去读配置元数据并潜在的替换值. PropertyPlaceholderConfigurer 有几个核心的父类, 一父类级 PlaceholderConfigurerSupport 以及实现了 BeanFactoryPostProcessor 接口的二级父类 PlaceholderConfigurerSupport.

小结

  • BeanFactoryPostProcessor 是 beanFactory 的后置处理器接口, 通过 BeanFactoryPostProcessor, 我们可以自定义 Spring 容器中的 bean 定义, BeanFactoryPostProcessor 是在 Spring 容器加载了 bean 的定义信息之后, bean 实例化之前执行;
  • BeanFactoryPostProcessor 类型的 bean 会被 Spring 自动检测, 在常规 bean 实例化之前被 Spring 调用;
  • BeanFactoryPostProcessor 的常用场景包括 Spring 中占位符的处理, 我们自定义的敏感信息的解密处理, 当然不局限与此;

BeanDefinitionRegistryPostProcessor

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {

   /**
    * 在标准初始化之后修改应用程序上下文的内部 bean 定义注册表.
    * 所有的常规 bean 定义都已经加载, 但是还没有实例化 bean.
    * 这允许在下一个后处理阶段开始之前添加更多 bean 定义.
    */
   void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

}

说明

BeanDefinitionRegistryPostProcessor 接口继承自 BeanFactoryPostProcessor 接口, 该处理器接口定义在 spring-bean 模块中, 但应用于 ApplicationContext 容器, 即该处理器是为 ApplicationContext 容器扩展而被设计的, BeanFactoryPostProcessor 处理器也是为扩展而设计的, 但是不同的是 BeanFactoryPostProcessor 可以通过在 BeanFactory 手工设置该处理器来执行处理器方法, 而 BeanDefinitionRegistryPostProcessor 即使在 BeanFactory 中手工设置也无法被被调用, 必须在 ApplicationContext 中才能被调用.

该处理器方法的调用时间是在完成 BeanDefinition 注册后, 实例化 bean 之前被调用的, 该处理主要用于修改 BeanDefinition 注册表信息, 它用于被 ApplicationContext 调用, 在 bean 注册到 IOC 后创建实例前修改 bean 定义和新增 bean 注册, 这个是在 context 的 refresh 方法调用.

BeanDefinitionRegistryPostProcessor 的一个典型应用是扫描指定包及其子包下面拥有指定注解的类, 你会发现在
BeanFactory 中并没有使用到该后处理器, 该后处理器为 Spring 容器扩展而设计的, IOC 容器只加载一些常规的 Bean 配置, 而像 @Service, @Repository, @Compent@Bean 等这些注解定义的 Bean 是 ApplicationContext 容器中才扩展出来的.

其中 BeanDefinitionRegistryPostProcessor 有一个典型的应用是 Mybatis 中的 @Mapper. 此外, 这里要注意的是 @Service, @Repository, @Compent@Bean 这些注解修饰的 Bean 并不是通过后处理器来注入的, 而是通过自定义命名空间解析器来注入的.

相关的应用

MapperScannerConfigurer

在 MyBatis 集成 Spring 的扩展包中 (mybatis-spring-xxx.jar), 就是通过 MapperScannerConfigurer 实现 BeanDefinitionRegistryPostProcessor 接口的 postProcessBeanDefinitionRegistry 方法来实现扫描 @Mapper 注解修饰的接口, 并向 BeanDefinition 注册表中注册一系列的 AnnotatedBeanDefinition 对象, 这样 Spring 就可以在后续的启动流程中向 IOC 容器注册 Mapper 接口对象实例了, 从而实现 Mybatis 与 Spring 的集成.

另外, Mybatis 中的那些 Mapper 接口, 会通过动态代理的方式生成一个接口的代理实例, 从而完成一些持久化操作, 这就是为什么 Mybatis 只需定义 Mapper 接口而不用实现类的原因; 并且通过 MapperScannerConfigurer 注入的 AnnotatedBeanDefinition 对象, 在实例化完成后其 Bean 对象是一个 MyBatis 的 MapperFactoryBean 对象, 该 MapperFactoryBean 实现了 Spring 的 FactoryBean 接口, 然后 Spring 容器在返回 Mapper 接口对象 Bean 的时候, 就会通过 FactoryBean 接口来代理这个 Mapper 接口, 该代理操作会委托 Mybatis 自己来完成.

总之,Mybatis 集成 Spring 中的 Mapper 接口, 其本质是一个 MapperFactoryBean, MapperFactoryBean 实现了 FactoryBean, 所以每个 Mapper 对象在实例化的时候会调用 FactoryBean#getObject() 方法, 创建一个 Mapper 的实例.

这部分内容来自: https://www.jianshu.com/p/e5f4014fa9fe

BeanPostProcessor

/**
 * 该接口作用是:
 * 如果我们需要在 Spring 容器完成 Bean 的实例化, 配置和其他的初始化后添加一些自己的逻辑处理
 * 我们就可以定义一个或者多个 BeanPostProcessor 接口的实现
 */
public interface BeanPostProcessor {

   /**
    * @PostConstruct 修饰的方法
    * InitializingBean#afterPropertiesSet: 设置完 Bean 的所有属性之后被调用
    * 调用<bean>配置中的 init-method 方法
    */
   Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

   /**
    * 调用<bean>配置中的 init-method 方法
    * BeanPostProcessor#postProcessAfterInitialization:Bean 执行初始化方法后被调用
    * @PreDestroy 修饰的方法
    * DisposableBean#destroy: 在 bean 被销毁的时候调用
    * 调用<bean>配置中的 destroy-method 方法
    */
   Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}

BeanPostProcessor 接口可以说是 Spring 最重要的接口, 提供了两个方法,

  • postProcessBeforeInitialization(bean, beanName): 在 bean 初始化之前调用.
  • postProcessAfterInitialization( bean,beanName): 在 bean 初始化之后调用.

整个调用顺序可以简单示意如下:

--> Spring IOC 容器实例化 Bean
--> 调用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
--> 调用 bean 实例的初始化方法
--> 调用 BeanPostProcessor 的 postProcessAfterInitialization 方法

可以看到, Spring 容器通过 BeanPostProcessor 给了我们一个机会对 Spring 管理的 bean 进行再加工. 比如: 我们可以修改 bean 的属性, 可以给 bean 生成一个动态代理实例等等. 一些 Spring AOP 的底层处理也是通过实现 BeanPostProcessor 来执行代理包装逻辑的.

在 bean 的创建过程中, Spring 会通过该接口的实例集合, 在特定的阶段遍历实例, 调用实例的两个方法, 拿到入参里的 bean 和 beanName, 对每一个 bean 进行反复的修饰后再返回.

通过提前注册 BeanPostProcessor 实例, 然后再用的时候, 取出对应类型的实例集合, 遍历调用方法, 可以在遵守开闭原则的情况下进行功能的拓展: 只需要往容器中注册 BeanPostProcessor 类型的 Bean, 实现方法即可. 对调用的代码没有任何侵入性.

作者: 天还下着毛毛雨
链接:https://www.jianshu.com/p/f4034d603624
来源: 简书
著作权归作者所有. 商业转载请联系作者获得授权, 非商业转载请注明出处.

InstantiationAwareBeanPostProcessor

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {

   /**
    * 说明:
    * 在调用 bean 构造函数实例化前被调用, IOC 层在调用 Bean 构造器实例化之前会先执行该处理器方法,
    * 如果该处理器方法返回一个非空对象, 则 IOC 容器会中断后续初始化流程,
    * 即后续的属性注入也就不再执行了, 直接返回该非空对象作为 Bean 的实例.
    *
    * 相关的应用:
    * AbstractAutoProxyCreator, Spring 中的自动代理机制中就是通过该处理器方法来实现的,
    * 它通过扩展该处理器方法, 在 IOC 层调用 Bean 构造器实例化之前会先执行该处理器方法,
    * 并遍历所有的 Bean 判断这个 Bean 是否可以被代理
    * 该实现机制是通过配置一个目标 Bean 与增强匹配的表达式来现实的,
    * 如 RegexpMethodPointcutAdvisor, 并通过该表达式判断每个 Bean 是否存有对应的增强器,
    * 如果存在说明该 bean 可以被自动代理,
    * 然后在 InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
    * 处理器方法中织入增强, 并返回代理后的代理类, 返回代理类后 IOC 就直接返回该 Bean 实例了,
    * 后续的属性注入则无法再执行了.
    */
   Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;

   /**
    * 说明:
    * Spring 调用构造器实例化 Bean, 然后将 Bean 包装为一个 BeanWrapper 后,
    * 并在所有的配置属性注入到 Bean 前该处理器方法被调用,
    * 该处理器方法的返回值是一个 Boolean 值, 它可以用来控制是否继续注入 Bean 属性,
    * 在 Spring 源码中属性注入方法 populateBean() 的执行步骤如下:
    * 1. 执行 InstantiationAwareBeanPostProcessor 处理器的 postProcessAfterInstantiation 方法,
    *    该函数可以控制程序是否继续进行属性填充;
    * 2. 根据注入类型 (byName/byType), 提取依赖的 bean, 并统一存入 PropertyValues 中;
    * 3. 执行 InstantiationAwareBeanPostProcessor#postProcessPropertyValues 方法, 属性获取完毕后,
    *    并在将 PropertyValues 注入到 Bean 前对属性的再次处理,
    *    典型应用是 requiredAnnotationBeanPostProcessor 类中对属性的验证;
    * 4. 将所有 PropertyValues 中的属性填充至 BeanWrapper 中.
    */
   boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;

   /**
    * 说明:
    * 该处理器方法是在 BeanWrapper 给 Bean 注入属性之前被调用的
    *
    * 相关的应用:
    * 1. AutowiredAnnotationBeanPostProcessor
    *    BeanWrapper 在将给定的属性值注入到目标 Bean 之前,
    *    Spring 会调用 AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues 处理器方法,
    *    将所有 @Autowired 注解修饰的依赖 Bean 注入到目标 Bean,
    *    也就说由 @Autowired 注解修饰的 Bean 属性最先被注入到 Bean 中
    *
    * 2. RequiredAnnotationBeanPostProcessor
    *    如果一个 bean 某些字段必须含有, 则可以使用 @Required 注释,
    *    RequiredAnnotationBeanPostProcessor#postProcessPropertyValues
    *    在所有属性注入到 Bean 前, 回去检查所有被 @Required 注解修饰的方法 (@Required 只能修饰方法),
    *    判断是否有对应的属性注入.
    *    如果任何带有 @Required 的属性未设置的话 将会抛出 BeanInitializationException 异常.
    *
    * 3. CommonAnnotationBeanPostProcessor
    *    CommonAnnotationBeanPostProcessor 通过扩展该处理器方法,
    *    将那些被 @Resource 注解修饰的属性注入到 Bean
    *
    * 4. PersistenceAnnotationBeanPostProcessor 执行 @PersistenceContext 等 JPA 注解的注入
    */
   PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds,
                                            Object bean, String beanName) throws BeansException;
}

SmartInstantiationAwareBeanPostProcessor

public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {

   /**
    * 在调用{@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation}
    * 前预测要返回 bean 的类型
    */
   Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException;

   // 确定一个实例化时要用的构造器方法
   Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException;

   /**
    * 该方法用于返回早期的 Bean 引用, 即半成品的 Bean, 已经实例化但是还没有注入属性
    * 比如: CircularityA 引用 CircularityB, CircularityB 引用 CircularityC, CircularityC 引用 CircularityA
    * 1. Spring 容器创建单例 "circularityA" Bean:
    *    首先依据无參构造器创建 "circularityA" Bean, 并暴露一个 ObjectFactory,
    *    这个 ObjectFactory 用于返回提前暴露的 circularityA,
    *    然后将 "circularityA" 放到 "当前创建的 Bean 缓存池" 中.
    *    然后进行 setter 注入"circularityB";
    *
    * 2. Spring 容器创建单例 "circularityB" Bean:
    *    首先依据无參构造器创建"circularityB" Bean, 并暴露一个 ObjectFactory,
    *    于返回提前暴露的 circularityB,
    *    然后将 circularityB 放入 "当前创建的 Bean 缓存池" 中,
    *    然后进行 setter 注入 circularityC;
    *
    * 3. Spring 容器创建单例 "circularityC" Bean:
    *    首先依据无參构造器创建"circularityC"Bean, 并暴露一个 ObjectFactory,
    *    用于返回提前暴露的 circularityC. 并将 circularityC 放入"当前创建的 Bean 缓存池"中,
    *    然后进行 setter 注入 circularityA ;
    *    进行注入"circularityA"时因为步骤 (1) 提前暴露了 circularityA 所以从之前的 Cache 里面拿 BeanA,
    *    而不用反复创建.
    *
    * 4. 最后在依赖注入"circularityB"和"circularityA"也是从 catch 里面拿提前暴露的 bean.
    *    完成 setter 注入.
    *
    * 该方法中, 如果入参 bean 是 circularityA 这个 Bean,
    * 则在第一次创建 circularityA 时会返回一个半成品的 Bean,
    * 已经实例化但是还没有注入属性, 我们称这个半成品的 bean 为 exposedObject,
    * 即早期暴露的 Bean. 当 circularityC 创建时, 会先注入这个半成品 beanA,
    * 这样就先完成了 BeanC 的创建, 接着会完成 BeanC 的创建,
    * 到最后 BeanA 时, BeanC 已经完成了创建, 所以 BeanA 也就可以顺利完成.
    *
    * 此外, 对于 "prototype" 作用域 Bean.
    * Spring 容器无法完成依赖注入, 由于 "prototype" 作用域的 Bean,
    * Spring 容器不进行缓存, 因此无法提前暴露一个创建中的 Bean.
    *
    * 还有就是, 构造函数循环依赖注入时, 也会抛异常.
    */
   Object getEarlyBeanReference(Object bean, String beanName) throws BeansException;

}

MergedBeanDefinitionPostProcessor

public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {

   /**
    * BeanDefinition 被包装为 BeanWrapper 后, 会调用该方法;
    * 典型的应用是将自动装配 @Autowired 注解修饰的属性保存到
    * RootBeanDefinition#externallyManagedConfigMembers, 方便后续注入到 Bean 实例
    */
   void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);

}

该处理器在 BeanFactory#doCreateBean 的运用场景 (常规 Bean 创建的执行步骤) 如下:

  1. 实例化 bean, 将 BeanDefinition 转换为 BeanWrapper, 这里是创建 bean 的地方, 由 createBeanInstance 方法来完成, 根据指定 bean 使用相应的策略 (如: 工厂方法, 构造函数自动注入, 简单初始化) 创建实例
    instanceWrapper = createBeanInstance(beanName, mbd, args);
  2. MergedBeanDefinitionPostProcessor 的应用
    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
  3. 依赖处理 (会应用 SmartInstantiationAwareBeanPostProcessor 处理器)
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences
                                                    && isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
    // 为避免后期循环依赖, bean 初始化完成前将创建实例的 ObjectFactory 加入缓存:
    addSingletonFactory(beanName, new ObjectFactory<Object>() {
      public Object getObject() throws BeansException {
         // 对 bean 再一次依赖引用, 主要应用 SmartInstantiationAwareBeanPostProcessor
         return getEarlyBeanReference(beanName, mbd, bean);
      }
    });
    }
  4. 属性填充, 将所有属性填充到 bean 实例中
    populateBean(beanName, mbd, instanceWrapper);

DestructionAwareBeanPostProcessor

public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {

   // 在 bean 实例销毁前, 将调用这个自定义销毁的回调.
   void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;
}

常见的 BeanPostProcessor 接口作用

InstantiationAwareBeanPostProcessor

postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)

在 bean 实例化之后, 属性注入之前对 Bean, 进行修改.

SmartInstantiationAwareBeanPostProcessor

determineCandidateConstructors()
  1. bean 实例化时, 获取合适的构造方法
  2. 解析 loopUp 注解, 添加到 bd 的 MethodOverrides

AutowiredAnnotationBeanPostProcessor

InstantiationAwareBeanPostProcessorAdapter

ImportAwareBeanPostProcessor

postProcessProperties(pvs,bean,beanName)

Bean 实现 EnhancedConfiguration 这个接口, 调用它的 setBeanFactory, 对我们没用, 业务代码无法实现 ConfigurationClassEnhancer.EnhancedConfiguration, 因为其非公共的 class.

MergedBeanDefinitionPostProcessor

AutowiredAnnotationBeanPostProcessor

  • postProcessMergedBeanDefinition(): 收集 @Autowired, @Value 的属性和方法
  • postProcessProperties(): 注入 @Autowired, @Value 的属性, 方法

InitDestroyAnnotationBeanPostProcessor

  • postProcessMergedBeanDefinition(): 收集 @PostConstruct, @PreDestroy
  • postProcessProperties(): 注入 @Resource 的属性
  • postProcessBeforeInitialization(): @ProConstrcut 方法的调用

CommonAnnotationBeanPostProcessor:

  • postProcessMergedBeanDefinition(): 收集 @Resource, 并调用父类 InitDestroyAnnotationBeanPostProcessor
  • postProcessMergedBeanDefinition(): 来收集 @PostConstruct, @PreDestroy

ApplicationListenerDetector

    applyBeanPostProcessorsAfterInitialization() : 判断是否是 ApplicationListener 类型, 有加入到事件管理器中

ApplicationContextAwareProcessor

postProcessBeforeInitialization :

EnvironmentAware,EmbeddedValueResolverAware,ResourceLoaderAware,

ApplicationEventPublisherAware,MessageSourceAware,ApplicationContextAware

接口的调用

ConfigurationClassPostProcessor.ImportAwareBeanPostProcessor

postProcessBeforeInitialization()

如果该类被 B 类 @import 进来, 那么该方法会传入 B 类的注解元数据 AnnotationMetadata

SmartInstantiationAwareBeanPostProcessor

AbstractAutoProxyCreator

  • applyBeanPostProcessorsAfterInitialization() : 符合条件生成代理, aop

注册 BeanPostProcessor 源码解析

public static void registerBeanPostProcessors(
            ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

    // 取出容器里 BeanPostProcessor 类型 的 bean 的 Name 数组
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

    // Register BeanPostProcessorChecker that logs an info message when
    // a bean is created during BeanPostProcessor instantiation, i.e. when
    // a bean is not eligible for getting processed by all BeanPostProcessors.
    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

    // 区分实现了 PriorityOrdered, Ordered 和 其他的处理器.
    // 用来装实现了 PriorityOrdered 接口的 BeanPostProcessor 实例
    List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    // 用来装内部的 BeanPostProcessor 实例
    List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
    // 用来装实现了 Ordered 接口的 BeanPostProcessor 实例
    List<String> orderedPostProcessorNames = new ArrayList<>();
    // 用来装其他的 BeanPostProcessor 实例
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();

    // 先是实例化实现了 PriorityOrdered 接口的
    for (String ppName : postProcessorNames) {
        if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            // 先实例化实现了 PriorityOrdered 接口的
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            // 加到容器中
            priorityOrderedPostProcessors.add(pp);
            // 判断是否是内部的
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        // 实现了 Ordered 接口的 , 加对应容器里
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
        }
        else {
            // 其他的, 加对应容器里
            nonOrderedPostProcessorNames.add(ppName);
        }
    }

    // 首先注册实现了 PriorityOrdered 的 BeanPostProcessor
    // 按 PriorityOrdered 排序
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    // 加到 beanFactory 中的 beanPostProcessors 容器
    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

    // 再注册 implement Ordered
    List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
    for (String ppName : orderedPostProcessorNames) {
        // 实例化
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        orderedPostProcessors.add(pp);
        // 内部的
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    // 按 Ordered 排序
    sortPostProcessors(orderedPostProcessors, beanFactory);
    // 加到 beanFactory 中的 beanPostProcessors 容器
    registerBeanPostProcessors(beanFactory, orderedPostProcessors);

    // 再处理  没实现排序接口的
    List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
    for (String ppName : nonOrderedPostProcessorNames) {
        // 实例化
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        nonOrderedPostProcessors.add(pp);
        // 内部的
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    // 加到 beanFactory 中的 beanPostProcessors 容器
    registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

    // 对内部的 BeanPostProcessor 实例排序
    sortPostProcessors(internalPostProcessors, beanFactory);
    // 注册
    registerBeanPostProcessors(beanFactory, internalPostProcessors);

    // Re-register post-processor for detecting inner beans as ApplicationListeners,
    // moving it to the end of the processor chain (for picking up proxies etc).
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

和处理 BeanFactoryPostProcessor 的流程差不多, 取出所有的, 按排序接口的优先级优先排序, 实例化, 然后注册到容器中.

补充说明

InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor 这两个分别是 Bean 在初始化和销毁之前的回调方法, SmartInstantiationAwareBeanPostProcessor 这个相当于 InstantiationAwareBeanPostProcessor 的扩展版本, 增加了一个对 Bean 类型预测的回调, 但这个主要是 Spring 框架内部用的, 用户还是用 InstantiationAwareBeanPostProcessor 即可. MergedBeanDefinitionPostProcessor 则是在合并处理 Bean 定义的时候的回调. 这个东东按我的理解也基本是框架内部使用的, 用户不用管.

BeanPostProcessor 使用场景

  • 处理自定义注解, bean 可以添加我们自定义的注解, 自定义的注解处理方式在该类中实现, 如通过注解识别一组或几组 bean, 在后续的业务处理中根据组 bean 进行逻辑.
  • 打印日志, 将每个 bean 的初始化情况打印出来; 打印初始化时间等.
  • 可以修改 bean 的属性
  • 可以给 bean 生成一个动态代理实例
  • Spring 根据配置注入同一接口的不同实现

作者: 一天一夜 00
链接:https://www.jianshu.com/p/e5f4014fa9fe
来源: 简书
著作权归作者所有. 商业转载请联系作者获得授权, 非商业转载请注明出处.

感觉这个作者写得很好, 很清楚, 本来想点个赞的, 结果发现要注册, 还是算了, 注明一下从这里复制的吧!

rainbow

没什么大用的码农; 贴图怪; bug制造者; 只会电脑开关机的开发;

文章评论