• Spring 源码阅读 13:执行 BeanFactoryPostProcessor 中的处理方法


    前情提要

    在之前一文中,提到 AbstractApplicationContext#refresh 方法是一个非常重要的方法,它包含了 Spring 容器初始化的整个流程。最近的一系列文章都在深入分析这个方法中的每一个步骤的具体原理,本文接着分析refresh方法中的以下两行代码:

    // Allows post-processing of the bean factory in context subclasses.
    // 这里默认是一个空的模版方法,子类可以在此处实现逻辑
    postProcessBeanFactory(beanFactory);
    
    // Invoke factory processors registered as beans in the context.
    // 执行 BeanFactory 的后处理器
    invokeBeanFactoryPostProcessors(beanFactory);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    postProcessBeanFactory 方法

    这里的 postProcessBeanFactory 其实是一个空方法:

     /**
    * Modify the application context's internal bean factory after its standard
    * initialization. All bean definitions will have been loaded, but no beans
    * will have been instantiated yet. This allows for registering special
    * BeanPostProcessors etc in certain ApplicationContext implementations.
    *  @param  beanFactory the bean factory used by the application context
    */
    protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    我特意把源码中的注释内容也贴在这里,这是一个protected修饰的空方法,也就是说,此处是留给子类的扩展点。方法的注释大意是说,这里可以在完成标准的初始化之后,对应用上下文内部的beanFactory进行修改,此时,所有的 BeanDefinition 都已经加载完毕,而 Bean 都还没有被创建,所以这里可以进行 BeanPostProcessor 的注册等。

    简而言之,这里的注释告诉了我们方法被调用的时机,以及在这里可以做的事情。不过,既然方法中会将beanFactory作为参数传递进来,那么任何对beanFactory的修改,在这里都可以做,比如操作之前已经注册的 BeanDefinition 等。

    不过 Spring 建议我们在此注册 BeanPostProcessor。至于对beanFactory的修改,放在本文后半部分要介绍的 BeanFactoryPostProcessor 更合适。

    这里有一点有必要再次提醒,在实现postProcessBeanFactory方法的时候,要注意它被调用的时机,要清楚方法被调用的时候,beanFactory 相关的工作已经完成了哪些,哪些工作还没做。(比如这里就是在 BeanDefinition注册之后,Bean初始化之前)。根据它被调用的时机可以推断出,这里是一个非常重要的扩展点。

    invokeBeanFactoryPostProcessors 方法

    下面看 invokeBeanFactoryPostProcessors 方法的具体内容。

     /**
    * Instantiate and invoke all registered BeanFactoryPostProcessor beans,
    * respecting explicit order if given.
    * 

    Must be called before singleton instantiation. */ protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor) if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } }

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    从注释中可以看出,这个方法要执行的工作是实例化并执行所有已经被注册的 BeanFactoryPostProcessor,这里关键内容是第一行的方法调用,具体的工作被委派给了 PostProcessorRegistrationDelegate 的同名静态方法方法。调用方法的参数中,getBeanFactoryPostProcessors()获取到的是当前应用上下文中的 BeanFactoryPostProcessor 列表,默认是一个空列表。

    查看这个方法的源码:

    public static void invokeBeanFactoryPostProcessors(
          ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) {
    
       // Invoke BeanDefinitionRegistryPostProcessors first, if any.
       Set processedBeans = new HashSet<>();
    
       if (beanFactory instanceof BeanDefinitionRegistry) {
          BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
          List regularPostProcessors = new ArrayList<>();
          List registryProcessors = new ArrayList<>();
    
          for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
             if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                BeanDefinitionRegistryPostProcessor registryProcessor =
                      (BeanDefinitionRegistryPostProcessor) postProcessor;
                registryProcessor.postProcessBeanDefinitionRegistry(registry);
                registryProcessors.add(registryProcessor);
             }
             else {
                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.
          List currentRegistryProcessors = new ArrayList<>();
    
          // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
          String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
          for (String ppName : postProcessorNames) {
             if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
             }
          }
          sortPostProcessors(currentRegistryProcessors, beanFactory);
          registryProcessors.addAll(currentRegistryProcessors);
          invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
          currentRegistryProcessors.clear();
    
          // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
          postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
          for (String ppName : postProcessorNames) {
             if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
             }
          }
          sortPostProcessors(currentRegistryProcessors, beanFactory);
          registryProcessors.addAll(currentRegistryProcessors);
          invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
          currentRegistryProcessors.clear();
    
          // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
          boolean reiterate = true;
          while (reiterate) {
             reiterate = false;
             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);
                   reiterate = true;
                }
             }
             sortPostProcessors(currentRegistryProcessors, beanFactory);
             registryProcessors.addAll(currentRegistryProcessors);
             invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
             currentRegistryProcessors.clear();
          }
    
          // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
          invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
          invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
       }
    
       else {
          // Invoke factory processors registered with the context instance.
          invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
       }
    
       // 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 priorityOrderedPostProcessors = new ArrayList<>();
       List orderedPostProcessorNames = new ArrayList<>();
       List 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 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 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();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132

    这个方法的代码有 100 多行,不过仔细看的话,这里面很多的逻辑是相似的。前面讲过,这个方法的作用是实例化和执行所有已经注册过的 BeanFactoryPostProcessor,因此,我们分析这段代码的目标就是看 Spring 如何找到这些 BeanFactoryPostProcessor,如何实例化它们,以及如何执行。

    分析之前,先简单介绍一下 BeanFactoryPostProcessor,前面我们介绍过 BeanPostProcessor,它提供了在 Bean 被初始化之前和之后对 Bean 进行操作的扩展点。BeanFactoryPostProcessor 与之类似,它只有一个postProcessBeanFactory方法,提供了在 BeanFactory 标准初始化完成之后,对其进行操作。

    你可能会觉得,这里提供的扩展点和前面介绍的postProcessBeanFactory方法的作用重复了,它们确实可以做同样的事情,但是仔细想一下,其实不然。在postProcessBeanFactory方法中,虽然可以对beanFactory做任何操作,但是 Spring 只是建议在此进行注册 BeanPostProcessor 等类似的操作。因为在实际的项目开发中,不同的模块,以及不同的第三方框架,都可能需要对beanFactory进行操作,但是这些不同模块和第三方框架对beanFactory操作的逻辑不可能放在同一个方法里,因此,更适合做这件事的是 BeanFactoryPostProcessor。将每一个对beanFactory的操作,放在一个 BeanFactoryPostProcessor 的实现中,并注册到 Spring 容器中,那么,此处的invokeBeanFactoryPostProcessors就会实例化并且执行相应的逻辑。

    言归正传,开始分析invokeBeanFactoryPostProcessors的源码,由于这个方法的代码比较多,为了方便查看分析,我会在分析到某一部分的时候,将那部分的代码片段再贴出来。

    防止重复执行

    首先,第一行代码创建了一个 Set 集合,用来保存 BeanFactoryPostProcessor 的名称。

    Set processedBeans = new HashSet<>();
    
    • 1

    在后续的流程中,会通过不同的方式从 Spring 容器中获取已经注册的 BeanFactoryPostProcessor,然后执行其中的逻辑。为了防止同一个 BeanFactoryPostProcessor 中的逻辑被重复执行,每当执行完一个之后,会将它的名称,添加到这个集合,以供后续的 BeanFactoryPostProcessor 执行前进行判断。因此,这个集合中保存的是已经执行过的 BeanFactoryPostProcessor。

    BeanDefinitionRegistryPostProcessor

    之后是一个条件判断:

    if (beanFactory instanceof BeanDefinitionRegistry) {
        /* 省略中间的代码块 */
    }
    
    • 1
    • 2
    • 3

    根据之前的源码分析可知,Spring 容器初始化创建的 BeanFactory 的类型是 ConfigurableListableBeanFactory,再结合 ConfigurableListableBeanFactory 继承关系(下图)可知,

    这里的条件判断结果为 true

    因此,我们查看方法体中的代码。

    BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
    List regularPostProcessors = new ArrayList<>();
    List registryProcessors = new ArrayList<>();
    
    for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
       if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
          BeanDefinitionRegistryPostProcessor registryProcessor =
                (BeanDefinitionRegistryPostProcessor) postProcessor;
          registryProcessor.postProcessBeanDefinitionRegistry(registry);
          registryProcessors.add(registryProcessor);
       }
       else {
          regularPostProcessors.add(postProcessor);
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    这里创建了两个列表,分别用于存放 BeanFactoryPostProcessor 的regularPostProcessors和用于存放 BeanDefinitionRegistryPostProcessor的registryProcessors,然后将方法参数传递进来的 BeanFactoryPostProcessor 列表中,实现了 BeanDefinitionRegistryPostProcessor 的添加到registryProcessors中,其余的添加到regularPostProcessors中。在分组的过程中,实现了 BeanDefinitionRegistryPostProcessor 接口的后处理器顺便执行了postProcessBeanDefinitionRegistry方法的处理逻辑。

    这里需要了解一下 BeanDefinitionRegistryPostProcessor 接口,一下是接口的定义。

    public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
    
       /**
    * Modify the application context's internal bean definition registry after its
    * standard initialization. All regular bean definitions will have been loaded,
    * but no beans will have been instantiated yet. This allows for adding further
    * bean definitions before the next post-processing phase kicks in.
    *  @param  registry the bean definition registry used by the application context
    *  @throws  org.springframework.beans.BeansException in case of errors
    */
    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    可以看到,它继承了 BeanFactoryPostProcessor 接口,并添加了一个接口方法postProcessBeanDefinitionRegistry,方法的参数类型 BeanDefinitionRegistry 定义如下:

    public interface BeanDefinitionRegistry extends AliasRegistry {
        void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
                 throws BeanDefinitionStoreException;
        void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
        BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
        boolean containsBeanDefinition(String beanName);
        String[] getBeanDefinitionNames();
        int getBeanDefinitionCount();
        boolean isBeanNameInUse(String beanName);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    从这个接口的名字、其中的方法、以及 BeanDefinitionRegistryPostProcessor 中postProcessBeanDefinitionRegistry方法的注释都可以看出,这里是为了在beanFactory初始化完成后,通过代码向beanFactory中添加新的 BeanDefinition。

    结合前面说的,BeanFactoryPostProcessor 中invokeBeanFactoryPostProcessors方法在 BeanDefinition 加载完之后、Bean 初始化之前执行。可以得出一个一个结论,postProcessBeanDefinitionRegistry方法需要先于invokeBeanFactoryPostProcessors方法被执行。这也是这里需要将参数传入的 BeanFactoryPostProcessor 根据是否实现了 BeanDefinitionRegistryPostProcessor 接口进行区分的原因。后续的执行逻辑中,需要将实现了 BeanDefinitionRegistryPostProcessor 接口的 BeanFactoryPostProcessor 找出来,先执行它们的postProcessBeanDefinitionRegistry方法。

    分批执行postProcessBeanDefinitionRegistry

    接着往下看

    List currentRegistryProcessors = new ArrayList<>();
    复制代码
    
    • 1
    • 2

    这里又创建了一个用于存放 BeanDefinitionRegistryPostProcessor 的列表,之前得到过一个结论,BeanDefinitionRegistryPostProcessor 接口中的postProcessBeanDefinitionRegistry方法需要先被执行,因此,之后的逻辑应该是要执行所有实现了 BeanDefinitionRegistryPostProcessor 的后处理器中的postProcessBeanDefinitionRegistry方法。

    这里创建了一个名叫currentRegistryProcessors的列表,保存当前执行的 Processor,是因为之后的逻辑中要对所有的 BeanDefinitionRegistryPostProcessor 分批执行它的处理逻辑。为什么要分批执行呢,接着看后面的逻辑。

    // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
    String[] postProcessorNames =
          beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    for (String ppName : postProcessorNames) {
       if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
          currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
          processedBeans.add(ppName);
       }
    }
    sortPostProcessors(currentRegistryProcessors, beanFactory);
    registryProcessors.addAll(currentRegistryProcessors);
    invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
    currentRegistryProcessors.clear();
    
    // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
    postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    for (String ppName : postProcessorNames) {
       if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
          currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
          processedBeans.add(ppName);
       }
    }
    sortPostProcessors(currentRegistryProcessors, beanFactory);
    registryProcessors.addAll(currentRegistryProcessors);
    invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
    currentRegistryProcessors.clear();
    
    // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
    boolean reiterate = true;
    while (reiterate) {
       reiterate = false;
       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);
             reiterate = true;
          }
       }
       sortPostProcessors(currentRegistryProcessors, beanFactory);
       registryProcessors.addAll(currentRegistryProcessors);
       invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
       currentRegistryProcessors.clear();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    可以看到三段相似的逻辑,并分别有注释说明,根据注释可以了解到,针对所有的 BeanDefinitionRegistryPostProcessor,会优先处理实现了 PriorityOrdered 接口的,然后处理实现了 Ordered 接口的,最后处理其余的。

    此处有必要简单介绍一下 PriorityOrdered 和 Ordered 接口。

    它们俩是继承关系,都只有一个getOrder方法,可以说是定义了同一种行为的两个接口。他们俩的区别主要在语义上,PriorityOrdered 代表优先级,Ordered 代表顺序。实现了这两个接口的类,需要在getOrder方法返回一个 Integer 类型的值,值越小代表优先级越高或者顺序越靠前。Spring 中的很多类都会实现这个接口,主要是为了处理多个同类型逻辑的时候,能提供优先级和顺序。

    回到代码中,先看这三段相似逻辑的第一段。

    String[] postProcessorNames =
          beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    for (String ppName : postProcessorNames) {
       if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
          currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
          processedBeans.add(ppName);
       }
    }
    sortPostProcessors(currentRegistryProcessors, beanFactory);
    registryProcessors.addAll(currentRegistryProcessors);
    invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
    currentRegistryProcessors.clear();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    首先,从beanFactory找到所有 BeanDefinitionRegistryPostProcessor 类型的 Bean 的名字,在这里因为 Bean 都还没有初始化,因此只需要获取beanName即可,后续对这些 Bean 的信息的判断,都是基于已经注册的 BeanDefinition。

    找到之后对所有找到的beanName进行遍历,判断beanName对应的 Bean 是否实现了 PriorityOrdered 接口,如果是的话,则通过调用beanFactorygetBean方法,获取到这个 Bean,并添加到currentRegistryProcessors中等待执行逻辑,再把它的名字添加到processedBeans中,确保之后它不会被重复执行。

    遍历完之后,所有即将要执行的 BeanDefinitionRegistryPostProcessor 都已经被实例化并添加到了currentRegistryProcessors中,接下来就是执行for循环代码块之后的 4 行代码,它们的作用分别如下:

    1. currentRegistryProcessors中的元素进行排序。
    2. currentRegistryProcessors中的元素都添加到registryProcessors中。(在此之前,registryProcessors中只有方法参数传递进来的 BeanDefinitionRegistryPostProcessor。
    3. 调用invokeBeanDefinitionRegistryPostProcessors方法执行currentRegistryProcessors中所有元素的postProcessBeanDefinitionRegistry方法。
    4. 清空currentRegistryProcessors列表。

    其中,invokeBeanDefinitionRegistryPostProcessors方法的代码如下,很简单。

    private static void invokeBeanDefinitionRegistryPostProcessors(
          Collection postProcessors, BeanDefinitionRegistry registry) {
    
       for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
          postProcessor.postProcessBeanDefinitionRegistry(registry);
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    至此,所有实现了 PriorityOrdered 接口的 BeanDefinitionRegistryPostProcessor 实例的postProcessBeanDefinitionRegistry方法就执行完了。

    后续的,实现了 Ordered 接口,以及其余的 BeanDefinitionRegistryPostProcessor 都会按照这样的方式实例化并执行postProcessBeanDefinitionRegistry方法,并且它们在执行前都要判断一下beanName是不是已经在processedBeans集合中了,只有不在集合中,也就是从来没被执行过的,才会被执行。

    以上,所有实现了 BeanDefinitionRegistryPostProcessor 的后处理器的 postProcessBeanDefinitionRegistry 方法都处理完了。接下来要处理所有后处理器的postProcessBeanFactory方法。

    分批执行postProcessBeanFactory

    接着看后面的代码,首先是这两行:

    invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    复制代码
    
    • 1
    • 2
    • 3

    这两行分别执行了registryProcessorsregularPostProcessors这两个列表中的后处理器的postProcessBeanFactory方法。

    invokeBeanFactoryPostProcessors方法的代码如下:

    private static void invokeBeanFactoryPostProcessors(
          Collection postProcessors, ConfigurableListableBeanFactory beanFactory) {
    
       for (BeanFactoryPostProcessor postProcessor : postProcessors) {
          postProcessor.postProcessBeanFactory(beanFactory);
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    现在再梳理一下这两个列表中的具体内容。在方法的开头,通过参数传入的后处理器列表中的元素,根据是否实现了 BeanDefinitionRegistryPostProcessor 被分别放入了这两个列表,然后,在执行容器中所有已注册的并实现了 BeanDefinitionRegistryPostProcessor 的后处理器的postProcessBeanDefinitionRegistry时,将他们都添加到了registryProcessors中。总结如下:

    • registryProcessors:实现了 BeanDefinitionRegistryPostProcessor 接口的,包含方法参数传入的和容器中已注册的。
    • regularPostProcessors:未实现 BeanDefinitionRegistryPostProcessor 接口的,只包含方法参数传入的。

    因此,这两行方法调用执行完之后,就只剩下容器中已注册且未实现 BeanDefinitionRegistryPostProcessor 接口的后处理器需要处理。看接下来的代码:

    // 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 priorityOrderedPostProcessors = new ArrayList<>();
    List orderedPostProcessorNames = new ArrayList<>();
    List 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 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 nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
    for (String postProcessorName : nonOrderedPostProcessorNames) {
       nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    这段逻辑和之前一部分的相似。先从容器中取出所有实现了 BeanFactoryPostProcessor 的beanName,把processedBeans中已经存在的排除,根据是否实现了 PriorityOrdered 或 Ordered 接口,将他们分成三组,然后分别对每组进行排序和postProcessBeanFactory方法的调用。

    其他

    方法的末尾,清除了beanFactory原数据缓存。

    beanFactory.clearMetadataCache();
    
    • 1

    至此,invokeBeanFactoryPostProcessors方法中的具体原理就分析完了,虽然代码错综复杂,但整体落逻辑很简单,只要搞懂所有 BeanFactoryPostProcessor 的执行顺序就可以了。

    整体的顺序总结如下:

    后续

    至此,Spring 完成了 BeanFactory 初始化之后,后处理器的处理工作。之后开始介绍 BeanPostProcessor 的注册。

    本文中分析的代码中,还多次调用了调用beanFactorygetBean方法,这是从容器中获取 Bean 实例的方法,如果是第一次获取,这里还包含 Bean 实例的初始化。这是 Spring 中非常重要的流程。之后也会详细介绍。

  • 相关阅读:
    redis(10)事务和锁机制
    原创AJAX + PHP 编辑器内容自动备份草稿保存到本地 (适用ueditor百度编辑器或其它) 内容变化后自动触发备份txt文件
    如何实现通达信接口开发?
    macOS文本编辑器 BBEdit 最新 for mac
    Java 开源重试类 guava-retrying 使用案例
    Linux基本操作
    论文分享|NeurIPS2022‘华盛顿大学|俄罗斯套娃表示学习(OpenAI使用的文本表示学习技术)
    Mac用NTFS文件夹读写NTFS硬盘 NTFS能复制多大的文件
    Django-(7)
    00后表示真干不过,部门新来的00后测试员已把我卷崩溃,想离职了...
  • 原文地址:https://blog.csdn.net/m0_70748381/article/details/127427138