掘金 后端 ( ) • 2022-06-25 13:43

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第28天,点击查看活动详情

在 xml 解析中我们知道了标签定义的实例通过解析为 Beandefinition 加载到 Spring 容器中,而解析的具体方法就在AbstractApplicationContext#refresh()方法中。而在容器实例化 Bean 之前,可以修改Beandefinition的信息,比如是否延迟加载、加入一些新的 Bean 的定义信息等,其具体实现就是 Bean 工厂的后置处理器BeanFactoryPostProcessor,并且通过invokeBeanFactoryPostProcessors()调用。

image-20211027104119398

1. Bean工厂的后置处理器

invokeBeanFactoryPostProcessors()主要完成对接口BeanFactoryPostProcessorBeanDefinitionRegistryPostProcessor的调用,在实例化之前,用此接口完成对 BeanDefinition 的动态修改

  • BeanFactoryPostProcessor,Bean工厂的后置处理器,用于Bean定义注册之后bean实例化之前;
  • BeanDefinitionRegistryPostProcessor,用于Bean定义注册之前。

image-20211027114328239

它的继承关系如下:

image-20211027115726399

1.1 BeanDefinitionRegistryPostProcessor

该接口是用来向容器中注册 BeanDefinition 的,BeanDefinition 的数目变多。

它的接口方法postProcessBeanDefinitionRegistry()执行的时机是,所有的“常规bean定义”都已注册完毕,该方法允许添加进一步的bean定义注册到容器中。

这里的“常规bean定义”指的是,在容器refresh前就已经注册好的bean定义。

1.2 BeanFactoryPostProcessor

该接口是用来修改容器中的BeanDefinition的,BeanDefinition的数目不变。

它的接口方法postProcessBeanFactory()执行的时机是,所有的BeanDefinition都已经注册完毕,不可能再增多了,该方法允许去修改BeanDefinition的一些属性。

1.3 手动创建BeanDefinition并添加到容器

常规的,如果要把一个 Bean 加载到 Spring 容器中,可以通过注解或者 XML 配置的方式,但实际上还有另外一种方法,就是手动添加到容器中去,如下面这个类:

import lombok.Data;
​
@Data
public class CustomBeanDefinition {
​
    private String name;
​
}

可以看到,类上并没有添加注解,当然 XML 文件中也不会配置,如果要把他添加到 Spring 容器中怎么办呢?

新建一个类实现BeanDefinitionRegistryPostProcessor,如下:

import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.stereotype.Component;
​
@Component
public class CustomBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
​
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        //创建一个 BeanDefinition 对象
        GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
        beanDefinition.setBeanClass(CustomBeanDefinition.class);
        MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
        propertyValues.addPropertyValue("name","手动创建BeanDefinition");
        //注册到注册中心去
        registry.registerBeanDefinition("customBeanDefinition",beanDefinition);
    }
​
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        //TODO 修改属性
    }
}

spring.xml 配置如下:

image-20211027162930902

测试类:

@Test
public void test() {
    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
    CustomBeanDefinition customBeanDefinition = applicationContext.getBean(CustomBeanDefinition.class);
    System.out.println(customBeanDefinition.getName());
}

测试结果:

image-20211027163208969

2. invokeBeanFactoryPostProcessors

BeanDefinition注册完毕之后,在refresh()方法中调用后置处理器:

image-20211027164113997

可以看到有一个代理类(PostProcessorRegistrationDelegate)专门来负责调用后置处理器方法,其中第二个参数就是我们手动添加的后置处理器实例(该方法的主要目的是拿到当前上下文中已经注册的 BeanFactoryPostProcessor,但在默认情况下是返回空的,一般情况下没有人添加,所以为空)。

/** BeanFactoryPostProcessors to apply on refresh. */
private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors = new ArrayList<>();
​
public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {
   return this.beanFactoryPostProcessors;
}

在进入到代理的回调方法,由于该方法非常复杂,这里通过片段的方式来分析,但也会把每一步的代码分析贴出来。

2.1 Spring 执行顺序

我们知道在 Spring 源码中大量的使用了策略模式,也就意味着有很多实现相同接口的实现类,所以在 Spring 容器加载的时候就存在优先级问题,如 BeanFactoryPostProcessorBeanDefinitionRegistryPostProcessor 的实现类大多数都有存在优先级的现象。

那么这些实现类的排序是如何定义的呢?

1、在Spring中,对类的顺序的处理是有统一的方案的,就是接口或注解。常见的就是@Order注解,实际上它的顶层是Ordered接口:

image-20211027171934096

需要注意的是,优先级最高的却是负数最小值,优先级最低的却是正数最大值。即数值越小优先级越高。

2、其次是 PriorityOrdered 接口,它继承了Ordered接口,从名字就能看出来该接口的优先级比 Ordered 接口要高。

image-20211027172154819

3、第三种就是既没有实现接口也没有标注解的类。

2.2 后置处理器的具体调用

上面为什么要将类的执行顺序,是因为在后置处理器的具体调用过程中就是按照上面的顺序来处理的,大致的调用规则如下:

  1. 先调用手动添加的后置处理器,再调用作为 BeanDenifition 注册的后置处理器;
  2. 先调用 BeanDefinitionRegistryPostProcessor 后置处理器并调用其postProcessBeanDefinitionRegistry()方法,再调用 BeanFactoryPostProcessor 后置处理器并调用其postProcessBeanFactory()方法;
  3. 先调用实现 PriorityOrdered 接口的,再调用实现 Ordered 接口的,最后是没有实现接口的。

按照上面的规则,在结合具体的代码,如下:

第一步,先调用手动添加的后置处理器:

image-20211027173614045

第二步,调用 BeanDefinitionRegistryPostProcessor 后置处理器,也就是配置文件或者注解加载的类,但调用的前提是上面规则的第 3 点,按照实现的排序接口排序调用并排序。

先调用实现了 PriorityOrdered 接口的 BeanDenifition 后置处理器。

image-20211027191536991

第三步,调用实现了 Ordered 接口的 BeanDenifition 后置处理器。

image-20211027192419196

第四步,再通过循环调用容器中剩余所有的 BeanDenifition 后置处理器。

image-20211027193030077

此处为什么要通过循环一直调用呢?因为这是在注册 BeanDenifition ,而且注册的BeanDenifition 可能又是一个BeanDenifition 注册后置处理器。

这很好理解,就像买饮料遇到再来一瓶一样的道理。

你买了 10 瓶,全部打开,有 8 个再来一瓶,老板又给了你 8 瓶,再全部打开,有 5 个再来一瓶,老板再给你 5 瓶,你接着再打开。

如此反复,直到没有遇到再来一瓶为止。

调用至此,所有注册 BeanDenifition 的方法都已经调完,这意味着 BeanDenifition 注册已经完毕,BeanDenifition 的数目也不会再增多了。

简单来说就是前面 4 步操作获取 BeanDefinitionRegistry 对象,如果我们能获取到这个对象就意味着可以获取这个对象中注册的所有 BeanDefinition 对象,我们拥有这个对象就可以完成里面所有 BeanDefinition 对象的修改和新增操作等等

第五步,调用所有 BeanDefinitionRegistry 的 postProcessBeanFactory() 方法,按需对 BeanDefinition 进行修改或完善,执行顺序和上面保持一致。

image-20211027213800794

到这里,入参 beanFactoryPostProcessors 和容器中的所有 BeanDefinitionRegistryPostProcessor 已经全部处理完毕,下一步开始处理容器中的所有 BeanFactoryPostProcessor。

我们看源码实际上可以发现,尽管它的代码很长,但实际上和前面非常类似,只是调用的对象变为了BeanFactoryPostProcessor ,包括优先级等等。

image-20211027215332643

唯一的不同点就是优先级直接通过一个循环就解决了,而不是每次都从容器中获取,原因是BeanDefinitionRegistryPostProcessor 处理远程之后 BeanDenifition 数量不会再变了,从容器中获取一次即可,一个循环就可以按实现的不同排序接口把它们分开。

到这,所有的 BeanDenifition 都已经修改完毕,BeanDenifition 的属性不会再有任何变化了。

3. 完整代码解析

public static void invokeBeanFactoryPostProcessors(
        ConfigurableListableBeanFactory beanFactory,
        List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
    // Invoke BeanDefinitionRegistryPostProcessors first, if any.
    // 先调用 BeanDefinitionRegistryPostProcessors 接口
    Set<String> processedBeans = new HashSet<>();
    // 判断传入的 beanFactory 是否实现了BeanDefinitionRegistry
    if (beanFactory instanceof BeanDefinitionRegistry) {
        // 强转
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
        // 用来保存 BeanFactoryPostProcessor 类型的后置处理器
        List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
        // 保存 BeanDefinitionRegistryPostProcessor 类型的后置处理器
        List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
        //循环传递进来的 beanFactoryPostProcessors
        for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
            //判断后置处理器是不是BeanDefinitionRegistryPostProcessor
            if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                BeanDefinitionRegistryPostProcessor registryProcessor =
                        (BeanDefinitionRegistryPostProcessor) postProcessor;
                //调用它的后置方法
                registryProcessor.postProcessBeanDefinitionRegistry(registry);
                //添加到registryProcessors(用于最后执行postProcessBeanFactory方法)
                registryProcessors.add(registryProcessor);
            }
            else {
                /**
                 * 若没有实现BeanDefinitionRegistryPostProcessor接口,那么他就是 BeanFactoryPostProcessor
                 * 把当前的后置处理器加入到regularPostProcessors中
                 */
                regularPostProcessors.add(postProcessor);
            }
        }
        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let the bean factory post-processors apply to them!
        // Separate between BeanDefinitionRegistryPostProcessors that implement
        // PriorityOrdered, Ordered, and the rest.
        //定义一个集合用于保存当前准备创建的 BeanDefinitionRegistryPostProcessor
        List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
        // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
        /*------------------------------------------begin--------------------------------------*/
        //第一步:去容器中获取BeanDefinitionRegistryPostProcessor的bean的处理器名称
        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class,
                        true, false);
        for (String ppName : postProcessorNames) {
            //判断是否实现了 PriorityOrdered 排序接口
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        //对currentRegistryProcessors集合中BeanDefinitionRegistryPostProcessor进行排序
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        registryProcessors.addAll(currentRegistryProcessors);
        /**
         * 执行 postProcessBeanDefinitionRegistry 方法
         * 在该处,将执行 ConfigurationClassPostProcessor,对配置类进行扫描,并注册BeanDefinition
         * 用于进行 bean 定义的加载 如我们的包扫描,@import等
         */
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        currentRegistryProcessors.clear();
        // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
        //接下来,调用实现 Ordered 的 BeanDefinitionRegistryPostProcessors
        postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class,
                true, false);
        for (String ppName : postProcessorNames) {
            //判断是否实现了 Ordered 排序接口
            if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        //排序
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        //加入到 registryProcessors 中
        registryProcessors.addAll(currentRegistryProcessors);
        //执行 postProcessBeanDefinitionRegistry 方法
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        currentRegistryProcessors.clear();
        // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
        boolean reiterate = true;
        while (reiterate) {
            reiterate = false;
            //找出所有实现BeanDefinitionRegistryPostProcessor接口的类
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class,
                    true, false);
            for (String ppName : postProcessorNames) {
                //跳过已经执行的
                if (!processedBeans.contains(ppName)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                    /**
                     * 如果有BeanDefinitionRegistryPostProcessor被执行, 则有可能会产生新的BeanDefinitionRegistryPostProcessor
                     * 因此这边将reiterate赋值为true, 代表需要再循环查找一次
                     */
                    reiterate = true;
                }
            }
            //排序
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            //加入到 registryProcessors 中
            registryProcessors.addAll(currentRegistryProcessors);
            //执行 postProcessBeanDefinitionRegistry 方法
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();
        }
        /*------------------------------------------end--------------------------------------*/
        // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
        /**
         * 调用所有 BeanDefinitionRegistryPostProcessor后置处理器 的 postProcessBeanFactory方法
         * 因为BeanDefinitionRegistryPostProcessor 继承自 BeanFactoryPostProcessor
         */
        invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
        /**
         * 最后, 调用入参beanFactoryPostProcessors中的普通BeanFactoryPostProcessor的postProcessBeanFactory方法
         */
        invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    }
    else {
        // Invoke factory processors registered with the context instance.
        invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    }
    /**
     * 到这里,入参 beanFactoryPostProcessors 和容器中的所有 BeanDefinitionRegistryPostProcessor 已经全部处理完毕,
     * 下一步开始处理容器中的所有 BeanFactoryPostProcessor。
     *
     * 我们看源码实际上可以发现,尽管它的代码很长,但实际上和前面非常类似,
     * 只是调用的对象变为了BeanFactoryPostProcessor ,包括优先级等等。
     */
    // Do not initialize FactoryBeans here: We need to leave all regular beans
    // uninitialized to let the bean factory post-processors apply to them!
    String[] postProcessorNames =
            beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
    // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
    // Ordered, and the rest.
    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    List<String> orderedPostProcessorNames = new ArrayList<>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    for (String ppName : postProcessorNames) {
        if (processedBeans.contains(ppName)) {
            // skip - already processed in first phase above
        }
        else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
        }
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
        }
        else {
            nonOrderedPostProcessorNames.add(ppName);
        }
    }
    // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
    // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
    List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
    for (String postProcessorName : orderedPostProcessorNames) {
        orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
    // Finally, invoke all other BeanFactoryPostProcessors.
    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
    for (String postProcessorName : nonOrderedPostProcessorNames) {
        nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
    // Clear cached merged bean definitions since the post-processors might have
    // modified the original metadata, e.g. replacing placeholders in values...
    beanFactory.clearMetadataCache();
}

4. 总结

经过对invokeBeanFactoryPostProcessors()方法源码的分析,可以知道该方法主要就是用来对BeanDefinitionRegistryPostProcessorBeanFactoryPostProcessor接口的调用,一个用于注册 BeanDefiition,一个用于对 BeanDefinition 的修改。

总的来说就是获取 BeanDefinitionRegistry 对象,获取到这个对象就可以获取这个对象中注册的所有 BeanDefinition 对象,拥有这个对象就可以完成里面所有 BeanDefinition 对象修改操作,而具体需要做什么,可以按照实际场景去定义。

另外一点需要注意的是 2 个后置处理器的入参 ConfigurableListableBeanFactoryBeanDefinitionRegistry本质上是一样的,也就是为什么下面这个判断会为 true。

image-20211028114514541

他们之间的关系如下:

image-20211028114653245

5. 参考