天天看点

Spring容器刷新—06-register-bean-post-processors

作者:当年三岁半
Spring容器刷新—06-register-bean-post-processors

这次的内容是上图中的第06步。

前言

通过前面几篇文章的介绍,在整个容器刷新过程中现在已经有了如下组件:

先来看看前面几篇文章都做了什么:

`01-prepareRefresh()`: `earlyApplicationListeners`、`applicationListeners` 、`initPropertySources()`、`validateRequiredProperties`
`02-obtainFreshBeanFactory()`: `refreshBeanFactory`
`03-prepareBeanFactory()`: `ignoreDependencyInterface`、`setBeanExpressionResolver`、`registerResolvableDependency`、`Environment`
`04-postProcessBeanFactory()`: 具体实现类的特殊逻辑(`Servlet` 等)
`05-invokeBeanFactoryPostProcessors()`: 可能发生的对 `BeanFactory/BeanDefinitionRegistry` 的修改操作           

也就是说,现在的 BeanFactory 已经完全准备好了,通过正常途径已经无法修改 BeanFactory 了。

接下来就要开始考虑单例 Bean 的初始化了,但是在此之前,还有好多的准备工作。

第一个准备工作就是本文要说的 registerBeanPostProcessors()。

registerBeanPostProcessors() 只是注册各种 BeanPostProcessor,还远远没到 BeanPostProcessor 执行的时候。

前置知识

看 registerBeanPostProcessors() 方法的名字就是要注册 BeanPostProcessor 了,那么先来了解一下 BeanPostProcessor 是什么。

BeanPostProcessor 是一个钩子函数,用来修改新创建的 Bean 实例,比如 检测标记在 Bean 上的标记接口或用代理对象包装 Bean。BeanPostProcessor 还有一系列的扩展子接口。

Spring容器刷新—06-register-bean-post-processors

下面就介绍几种常见的 BeanPostProcessor。

BeanPostProcessor

public interface BeanPostProcessor {

    /**
     * 在任何 「Bean初始化方法」(比如说InitializingBean#afterPropertiesSet) 回调之前, 将该 BeanPostProcessor 应用于一个给定的新的Bean实例.
     *
     * 此处传入的 Bean 已经经过 populateBean 填充属性了.
     * 返回的 bean 实例可能是对原始bean的包装.
     * 默认实现: 原样返回给定的 Bean
     *
     * 如果返回 null, 则不会调用后续的 BeanPostProcessors.
     *
     * @return 原始对象或者对原始对象的包装;
     */
    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    /**
     * 在任何 「Bean初始化方法」(比如说InitializingBean#afterPropertiesSet) 回调之后, 将该 BeanPostProcessor 应用于一个给定的新的Bean实例.
     *
     * 此处传入的 Bean 已经经过 populateBean 填充属性了.
     * 返回的 bean 实例可能是对原始bean的包装.
     *
     * 对于 FactoryBean 的情况而言,该回调方法既可以对 FactoryBean 实例本身回调, 也可以对 FactoryBean 返回的对象回调(从 Spring 2.0 开始).
     * 具体实现可以自己决定是否回调 FactoryBean 实例 或/和 FactoryBean 返回的实例.
     *
     * 与其他的回调方法不同, 该回调方法也可以被 InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 触发
     *
     * 默认实现: 原样返回给定的 Bean
     *
     * 如果返回 null, 则不会调用后续的 BeanPostProcessors.
     *
     * @return 原始对象或者对原始对象的包装;
     */
    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

}           

InstantiationAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor 是 BeanPostProcessor 的子接口,主要扩展了如下的方法:

  • 扩展了一个在 Bean 实例化 之前的回调
  • 扩展了一个在 Bean 实例化 之后, 但在 Bean 填充属性或自动装配发生之前的回调

一般用于拦截特定目标对象的默认实例化,比如创建(池化、懒加载等)代理对象。或者实现特定的注入策略,比如字段注入。

该接口是一个特殊接口,主要在框架内部使用。一般场景,建议尽可能实现简单的 BeanPostProcessor 接口。而不是使用该接口。
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {

    /**
     * 在目标bean实例化之前回调该BeanPostProcessor.
     *
     * 返回的bean对象可能是代理对象,而不是目标bean,从而拦截了目标bean的默认实例化.
     *
     * 如果该方法返回了非空对象,则当前bean的创建过程将被短路.
     * 短路之后唯一会被进一步调用的是来自BeanPostProcessors的postProcessAfterInitialization方法。
     *
     * 默认实现: 返回 null
     *
     * @return 代理对象 或 返回null以继续Bean的默认实例化流程
     */
    @Nullable
    default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        return null;
    }

    /**
     * 回调时机: Bean 被[实例化]之后(构造器或工厂方法),但在spring填充属性或自动装配之前
     *
     * 这里是实现用户自定义字段注入的完美时机,刚好在 spring 的自动注入之前.
     *
     * 默认实现: return true
     *
     * @return true: 表示应该给当前Bean填充属性;
     * false: 对当前Bean的属性填充应该被跳过;
     *
     * 返回false还会阻止在当前bean实例上回调任何后续的InstantiationAwareBeanPostProcessor实例。
     */
    default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        return true;
    }

    /**
     * 在工厂将给定的属性值应用于给定的bean之前,对当前Bean进行处理
     *
     * 如果具体实现类提供来自定义的postProcessPropertyValues实现,则应返回null(默认值),否则返回pvs
     *
     * @return the actual property values to apply to the given bean (can be the passed-in
     * PropertyValues instance), or {@code null} which proceeds with the existing properties
     * but specifically continues with a call to {@link #postProcessPropertyValues}
     * (requiring initialized {@code PropertyDescriptor}s for the current bean class)
     */
    @Nullable
    default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
            throws BeansException {

        return null;
    }

    /**
     * Post-process the given property values before the factory applies them
     * to the given bean. Allows for checking whether all dependencies have been
     * satisfied, for example based on a "Required" annotation on bean property setters.
     * <p>Also allows for replacing the property values to apply, typically through
     * creating a new MutablePropertyValues instance based on the original PropertyValues,
     * adding or removing specific values.
     * <p>The default implementation returns the given {@code pvs} as-is.
     * @param pvs the property values that the factory is about to apply (never {@code null})
     * @param pds the relevant property descriptors for the target bean (with ignored
     * dependency types - which the factory handles specifically - already filtered out)
     * @param bean the bean instance created, but whose properties have not yet been set
     * @param beanName the name of the bean
     * @return the actual property values to apply to the given bean (can be the passed-in
     * PropertyValues instance), or {@code null} to skip property population
     * @throws org.springframework.beans.BeansException in case of errors
     * @see #postProcessProperties
     * @see org.springframework.beans.MutablePropertyValues
     * @deprecated as of 5.1, in favor of {@link #postProcessProperties(PropertyValues, Object, String)}
     */
    @Deprecated
    @Nullable
    default PropertyValues postProcessPropertyValues(
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {

        return pvs;
    }

}           

DestructionAwareBeanPostProcessor

DestructionAwareBeanPostProcessor 是 Bean 被销毁之前的回调接口。所谓的销毁指的是: DisposableBean.destroy()、 destroy-method 等。

public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {

    /**
     * Bean 被销毁之前回调
     */
    void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;

    /**
     * 当前 Bean 是否需要被销毁
     * @since 4.3
     */
    default boolean requiresDestruction(Object bean) {
        return true;
    }

}           

registerBeanPostProcessors

这一步就是给 BeanFactory 中注册各种 BeanPostProcessor,那么最终注册到哪里去了呢?

addBeanPostProcessor

看看下面的 addBeanPostProcessors() 和 addBeanPostProcessor() 方法就明白了。

值得注意的是,这两个方法虽然名字看起来是 add,但是实际上他的作用应该是: removeAndAddToLast 的意思,就是每次先删掉之前的,再将新增的放到最后。

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {

    private final List<BeanPostProcessor> beanPostProcessors = new BeanPostProcessorCacheAwareList();

    public void addBeanPostProcessors(Collection<? extends BeanPostProcessor> beanPostProcessors) {
        this.beanPostProcessors.removeAll(beanPostProcessors);
        this.beanPostProcessors.addAll(beanPostProcessors);
    }

    @Override
    public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
        Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
        // Remove from old position, if any
        this.beanPostProcessors.remove(beanPostProcessor);
        // Add to end of list
        this.beanPostProcessors.add(beanPostProcessor);
    }
}           

继续看 registerBeanPostProcessors(),实际上最终是委托给了 PostProcessorRegistrationDelegate.registerBeanPostProcessors(ConfigurableListableBeanFactory, AbstractApplicationContext) 这个工具方法。

源码流程

方法刚开始还是和上一篇介绍的 invokeBeanFactoryPostProcessors 一样,来了一大波提示信息,大概意思是:

这个方法看起来写的很啰嗦,好像很容易优化。但是在你优化之前先瞅瞅 github 已经被拒绝的的 PR 列表……
final class PostProcessorRegistrationDelegate {
    public static void registerBeanPostProcessors(
            ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

        // WARNING: Although it may appear that the body of this method can be easily
        // refactored to avoid the use of multiple loops and multiple lists, the use
        // of multiple lists and multiple passes over the names of processors is
        // intentional. We must ensure that we honor the contracts for PriorityOrdered
        // and Ordered processors. Specifically, we must NOT cause processors to be
        // instantiated (via getBean() invocations) or registered in the ApplicationContext
        // in the wrong order.
        //
        // Before submitting a pull request (PR) to change this method, please review the
        // list of all declined PRs involving changes to PostProcessorRegistrationDelegate
        // to ensure that your proposal does not result in a breaking change:
        // https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate+is%3Aclosed+label%3A%22status%3A+declined%22

        // 这里依然是小心翼翼仅仅获取了 BeanPostProcessor 类型的 beanName,还不能调用 getBean()
        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.

        // beanFactory.getBeanPostProcessorCount(): 当前 BeanFactory 中已经存在的 BeanPostProcessor 数量
        // +1: 加的 1 就是 `BeanPostProcessorChecker` 自己
        // postProcessorNames.length: 指的是在下面一大波循环中要新增到 BeanFactory 中的 BeanPostProcessor
        int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;

        // BeanPostProcessorChecker就是来检测: 在 BeanPostProcessor 初始化的过程中有没有导致普通的 Bean 初始化
        // 如果有: 就打印一堆信息提醒你, 有 Bean 被过早初始化了

        // 为什么要提醒: 因为现在还在创建 BeanPostProcessor,
        // 但是这个过程中你突然创建了一个普通 Bean,
        // 那么你这个过早被创建的普通 Bean 可能无法被 BeanPostProcessor 增强(比较 BeanPostProcessor 自己都还在创建过程中呢)
        beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

        // 还是老套路: 将 BeanPostProcessor 分类(4大类)

        // 需要注意的是第1类和第2类是通过 getBean 创建出来的实例,其他两类都是 beanName(避免过早实例化)
        // 需要注意的是第1类和第2类是通过 getBean 创建出来的实例,其他两类都是 beanName(避免过早实例化)
        // 需要注意的是第1类和第2类是通过 getBean 创建出来的实例,其他两类都是 beanName(避免过早实例化)

        // Separate between BeanPostProcessors that implement PriorityOrdered,
        // Ordered, and the rest.
        // 第 1 类: 实现了 PriorityOrdered 接口的
        List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
        // 实现了 `PriorityOrdered` 接口的 BeanPostProcessor 还有个细分的类型
        // 第 2 类: MergedBeanDefinitionPostProcessor 类型的 BeanPostProcessor
        List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
        // 第 3 类: 实现了 Ordered 接口的
        List<String> orderedPostProcessorNames = new ArrayList<>();
        // 第 4 类: 普通的 BeanPostProcessor
        List<String> nonOrderedPostProcessorNames = new ArrayList<>();
        for (String ppName : postProcessorNames) {
            // 第 1 类
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                // 这里是通过 getBean 真真正正创建了 BeanPostProcessor 类型的 Bean
                // 而不是 beanName
                BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
                priorityOrderedPostProcessors.add(pp);
                // 第 2 类
                if (pp instanceof MergedBeanDefinitionPostProcessor) {
                    internalPostProcessors.add(pp);
                }
            }
            // 第 3 类
            else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                orderedPostProcessorNames.add(ppName);
            }
            // 第 4 类
            else {
                nonOrderedPostProcessorNames.add(ppName);
            }
        }

        // 经过上面的循环,已经给各种 BeanPostProcessor 分好类了
        // 下面就是按照不同类型的优先级注册到 BeanPostProcessor 中

        // 1. 先注册实现了 `PriorityOrdered` 接口的 BeanPostProcessor
        // First, register the BeanPostProcessors that implement PriorityOrdered.
        sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
        // 其实就是调用了 beanFactory.addBeanPostProcessor 给当前 BeanFactory 中新增 BeanPostProcessor
        // 作用是: 将给定的 BeanPostProcessor 添加到最后
        registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

        // 2. 注册实现了 `Ordered` 接口的 BeanPostProcessor
        // Next, register the BeanPostProcessors that implement Ordered.
        // 先通过 getBean 创建实例,然后注册
        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);
            }
        }
        sortPostProcessors(orderedPostProcessors, beanFactory);
        registerBeanPostProcessors(beanFactory, orderedPostProcessors);

        // 3. 普通的 BeanPostProcessor
        // Now, register all regular BeanPostProcessors.
        // 先通过 getBean 创建实例,然后注册
        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);
            }
        }
        registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

        // 4. 注册 internalPostProcessors
        // 所谓的 `internalPostProcessors` 指的就是 `MergedBeanDefinitionPostProcessor` 这种子接口 
        // Finally, re-register all internal BeanPostProcessors.
        sortPostProcessors(internalPostProcessors, beanFactory);
        registerBeanPostProcessors(beanFactory, internalPostProcessors);

        // 5. 将 `ApplicationListenerDetector` 移动到最后
        // 就是来处理实现了 `ApplicationListener` 这种事件接口的 Bean 的
        // 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));
    }
}           

BeanPostProcessorChecker

现在回头再看看 BeanPostProcessorChecker。他是用来检测:在 BeanPostProcessor 的初始化过程中是不是有其他普通的 Bean 被过早初始化了。

  • 什么叫普通的 Bean: 除了 BeanPostProcessor 类型和 BeanDefinition.role == RootBeanDefinition.ROLE_INFRASTRUCTURE 的 Bean 都是普通 Bean
  • 什么叫过早初始化: 一个普通 Bean 的正常创建流程应该经过一系列的 BeanPostProcessor 处理,但是现在 BeanPostProcessor 自己还在初始化过程中呢。这时候如果初始化一个普通的 Bean ,就无法保证这个普通 Bean 被所有的 BeanPostProcessor 处理,也就是说 Bean 被提前初始化了。

成员变量 beanPostProcessorTargetCount 什么意思呢?

其实就是上面代码中的 int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length; 这一行。

  • beanFactory.getBeanPostProcessorCount(): 指的是 BeanFactory 中已经存在的 BeanPostProcessor 实例的个数
  • +1: 指的是 BeanPostProcessorChecker 自己
  • postProcessorNames.length: 指的是经过上面的几波循环之后新增了多少 BeanPostProcessor 的实例
private static final class BeanPostProcessorChecker implements BeanPostProcessor {

    private static final Log logger = LogFactory.getLog(BeanPostProcessorChecker.class);

    private final ConfigurableListableBeanFactory beanFactory;

    private final int beanPostProcessorTargetCount;

    public BeanPostProcessorChecker(ConfigurableListableBeanFactory beanFactory, int beanPostProcessorTargetCount) {
        this.beanFactory = beanFactory;
        this.beanPostProcessorTargetCount = beanPostProcessorTargetCount;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        // 除了 BeanPostProcessor 类型 和 BeanDefinition.role == `RootBeanDefinition.ROLE_INFRASTRUCTURE`
        if (!(bean instanceof BeanPostProcessor) && !isInfrastructureBean(beanName) &&
                // 这个小于判断如果成立的话 就说明现在还有 `BeanPostProcessor` 没有实例化完成
                this.beanFactory.getBeanPostProcessorCount() < this.beanPostProcessorTargetCount) {
            if (logger.isInfoEnabled()) {
                logger.info("Bean '" + beanName + "' of type [" + bean.getClass().getName() +
                        "] is not eligible for getting processed by all BeanPostProcessors " +
                        "(for example: not eligible for auto-proxying)");
            }
        }
        return bean;
    }

    private boolean isInfrastructureBean(@Nullable String beanName) {
        if (beanName != null && this.beanFactory.containsBeanDefinition(beanName)) {
            BeanDefinition bd = this.beanFactory.getBeanDefinition(beanName);
            return (bd.getRole() == RootBeanDefinition.ROLE_INFRASTRUCTURE);
        }
        return false;
    }
}           

小节

通过这一步,所有的 BeanPostProcessor 的实例已经被创建了。并且都被注册到了 BeanFactory 中了。

但是需要注意的是,这里仅仅是 BeanPostProcessor 自己的实例化和注册,还没到 BeanPostProcessor 执行的时候呢。

后续的 Bean 创建过程中,这些 BeanPostProcessor 就可以发挥作用了。

继续阅读