Spring中invokeBeanFactoryPostProcessors方法的源码详细解读

1,071 阅读10分钟

前言

如果说spring里面哪个代码最有意思,我觉得,非本篇要谈的invokeBeanFactoryPostProcessors方法不可?为什么我会这么觉得,因为,这段代码,第一次看,可能会觉得很多相似的、甚至一模一样的地方,感觉很冗余。但仔细研究后,就会发现里面考虑很多情况,甚至这些逻辑会让阅读源码的人,好像行走在迷宫里。今天,我尝试着用我的方法,带着迷失在这一大段源码海洋里的人,走出来。

了解几个增强器相关的接口

我们先了解两个十分重要的接口BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor。 看下源码中的定义。

  1. BeanFactoryPostProcessor接口
public interface BeanFactoryPostProcessor {
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
  1. BeanDefinitionRegistryPostProcessor接口

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
  • BeanFactoryPostProcessor:对BeanFactory的增强处理,关于这个接口的扩展,我们会单独用一篇文章详细说明。
  • BeanDefinitionRegistryPostProcessor:与BeadDefinition相关的增强器,继承自BeanFactoryPostProcessor。除了继承的增强BeanFactory功能外,还能够实现动态的将Bean注册到Spring容器中。
  1. BeanDefinitionRegistry及其上下游的主要相关类的继承结构图。

下图是BeanDefinitionRegistry上下游的主要相关类的继承结构图。从这张图我们可以看出DefaultListableBeanFactoryBeanDefinitionRegistry的实现类。 该类定义了一组对BeanDefinition增删改查等基本操作的接口规范。 至于图中其他类的具体情况,有兴趣的小伙伴可以参考图中说明,并结合源码,自行分析即可。

了解几个顺序相关的接口

  1. Ordered接口
public interface Ordered {
	int HIGHEST_PRECEDENCE = Integer.MIN_VALUE;
	int LOWEST_PRECEDENCE = Integer.MAX_VALUE;
	int getOrder();
}
  1. PriorityOrdered接口
public interface PriorityOrdered extends Ordered {
}

上面两个接口,是用来反映对象的优先级别。Ordered接口中定义了顺序的上下限,以及获取顺序的方法,getOrder()返回的值越小,优先级越高。PriorityOrdered 继承自 Ordered,没有定义任何规范,它的优先级要高于 Ordered

上面简单描述了优先级的两个接口所约定的规范,那么Spring中一般是如何来保证这一规范得以实现的呢?这就要看下面的接口OrderComparator

  1. OrderComparator 顺序比较器
public class OrderComparator implements Comparator<Object> {
    @Override
    public int compare(@Nullable Object o1, @Nullable Object o2) {
        return doCompare(o1, o2, null);
    }

    private int doCompare(@Nullable Object o1, @Nullable Object o2, @Nullable OrderSourceProvider sourceProvider) {
        boolean p1 = (o1 instanceof PriorityOrdered);
        boolean p2 = (o2 instanceof PriorityOrdered);
        if (p1 && !p2) {
            return -1;
        }
        else if (p2 && !p1) {
            return 1;
        }

        int i1 = getOrder(o1, sourceProvider);
        int i2 = getOrder(o2, sourceProvider);
        return Integer.compare(i1, i2);
    }

    public static void sort(List<?> list) {
		if (list.size() > 1) {
			list.sort(INSTANCE);
		}
	}

	public static void sort(Object[] array) {
		if (array.length > 1) {
			Arrays.sort(array, INSTANCE);
		}
	}

	public static void sortIfNecessary(Object value) {
		if (value instanceof Object[]) {
			sort((Object[]) value);
		}
		else if (value instanceof List) {
			sort((List<?>) value);
		}
	}
    
    // 其他方法。略
}
  • 在该类中,定义并实现了3个静态排序方法:sort(List<?> list)、sort(Object[] array)、sortIfNecessary(Object value),用来实现数组和集合进行排序。
  • doCompare:该方法保证了Ordered接口所定义规范的落实。通过该源码我们也可以证实,对两个对象而言:
    1. 实现了不同的排序接口的:实现PriorityOrdered的优先级高于实现Order的对象;实现Order接口的对象,其优先级高于未实现任何排序接口的对象。
    2. 实现了同一个排序接口的(Ordered或者PriorityOrdered):比较getOrder()返回值,值越小、优先级越高。 对于我们今天要讨论的invokeBeanFactoryPostProcessors()方法,是通过优先获取PriorityOrdered、再获取Ordered等来保证处理顺序的(这两类接口内部再根据order排序)

既然这里提到了BeanDefinitionRegistry,那么就简单提一下BeanDefinition及相关类的继承结构图,方便对照学习。如下所示:

invokeBeanFactoryPostProcessors

委派执行

下面进入今天的主题,invokeBeanFactoryPostProcessors()方法的执行流程。 该方法的实现,实际上是委托给了PostProcessorRegistrationDelegate类,如下。当我们基于配置文件的方式完成注入时,参数beanFactory的实际类型为DefaultListableBeanFactory,这是个有故事的类,我们后面会多次遇到,会慢慢道尽。Bean定义相关的两个重要属性Map和List就藏在这个类里面,所以可以说这是个宝藏类。

AbstractApplicationContext.java

  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()));
      }
  }

PostProcessorRegistrationDelegate

下面是本方法真正的核心部分。由于总体上逻辑比较长,这里使用总分总的说明方式来叙述。

方法的总体结构设计

我这里将源码掏空,只保留总体的流程框架和步骤编号,如下

public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors)

        // 默认进入if逻辑
        // 第一块
	if (beanFactory instanceof BeanDefinitionRegistry) {
    	
        // 步骤1.1:处理方法参数beanFactoryPostProcessors
        
        // 步骤1.2:从所有的BeanDefinitionRegistryPostProcessor实现类中筛选出、实现了PriorityOrdered接口的类, 并处理和标记
        
        // 步骤1.3:从所有未被标记的BeanDefinitionRegistryPostProcessor实现类中筛选出、实现了Ordered接口的类, 并处理和标记
        // 步骤1.4:循环获取、所有未被标记的BeanDefinitionRegistryPostProcessor实现类,并处理和标记
    
        // 步骤1.5 执行BeanFactoryPostProcessor的postProcessBeanFactory()方法
        invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    
    } else {
    	// 直接执行
    	invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    }
    
    
    // 下面是第二块
    
    // 步骤2.1:从所有的BeanFactoryPostProcessor实现类中筛选出、实现了PriorityOrdered接口的类, 并处理和标记
        
    // 步骤2.2:从所有未被标记的BeanFactoryPostProcessor实现类中筛选出、实现了Ordered接口的类, 并处理和标记
              
    // 步骤2.3:从所有未被标记的BeanFactoryPostProcessor实现类,并处理和标记
}

下面通过一张流程图,将上面涉及到的核心步骤抽象出来

通过上面的源码和流程图可以看出来,作者在处理时,优先处理的是第一块中的子类,然后再在第二块中去处理父类。这两个接口的继承关系在本篇的开头部分已经给出来说明。这里的第一块和第二块、主角分别是BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor

分别说明每个步骤

第一块

  • 步骤1.1

第一块的代码,默认会进入if里的流程,这里简单再回顾一下,由于传入的第一个参数beanFactory的实际类型DefaultListableBeanFactoryBeanDefinitionRegistry的实现类,所以会进入if的逻辑之中。

下面给出步骤1.1中的源码

      BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
      List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
      List<BeanDefinitionRegistryPostProcessor> 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);
          }
      }

代码如上。在前面的小节,我们分析了BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor这两个接口,前者是后者的子接口。
在该步骤中,遍历方法的第二个参数beanFactoryPostProcessors,找出子类和父类,并归档。同时,直接完成了子类中方法的调用。父类中的方法在后面会统一调用。

  • 找出BeanDefinitionRegistryPostProcessor这个子接口的所有实现,放入registryProcessor集合;并完成该接口中独有的方法postProcessBeanDefinitionRegistry()的调用;
  • 找出BeanFactoryPostProcessor这个父接口的所有实现,归档存入regularPostProcessors集合。
  • 步骤1.2

从所有的BeanDefinitionRegistryPostProcessor实现类中筛选出、实现了PriorityOrdered接口的类, 并处理和标记。 源码如下:

    // 步骤1.2
    // BeanDefinitionRegistryPostProcessor && 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集合中
    registryProcessors.addAll(currentRegistryProcessors);
    // 完成调用处理逻辑
    invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
    // 处理完毕, 同样清除掉, 给下次再次使用
    currentRegistryProcessors.clear();

这里需要先明确几个变量的作用:

Set<String> processedBeans:处理过的Processor, 放入该集合。其实就是一个标记作用,防止在遍历和过滤的时候,重复处理。

List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors:我们在前面总的结构了分成了1.11.21.3等很多小步骤、这个集合的作用就是保存每一个小步骤中要处理的资源。每个步骤结束后该集合就要重置。

List<BeanDefinitionRegistryPostProcessor> registryProcessors:在步骤1.1中已经见过了,存放的是实现了registryProcessors的Processor实例。

步骤1.2的大致过程如下:

  1. 找到所有的BeanDefinitionRegistryPostProcessor
  2. 遍历、并筛选出实现了PriorityOrdered接口的PostProcessor
  3. 实例化筛选出来的PostProcessor(通过getBean()方法)
  4. 进行标记和统一处理
  • 步骤1.3 该步骤和1.2类型,区别在于,这次的顺序主角换成了Ordered,直接上源码
    postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    
    for (String ppName : postProcessorNames) {
    	// 从未标记过的postProcessorNames中, 筛选出实现了PriorityOrdered的
        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();
  • 步骤1.4 来看源码:
    boolean reiterate = true;
    while (reiterate) {
        reiterate = false;
        // 再根据类型获取一遍, 得到名称集合
        postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            // 上面没过滤到的漏网之BeanDefinitionRegistryPostProcessor, 放在这里进行实例化
            // 其实就是没排序的Processor, 这个做兜底处理
            if (!processedBeans.contains(ppName)) {
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);

                // 并且把标记需要在循环一次,因为之后新的BeanDefinitionRegistryPostProcessor的调用可能注册新的BeanDefinitionRegistryPostProcessor
                reiterate = true;
            }
        }
        // 排序、收集、调用
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        registryProcessors.addAll(currentRegistryProcessors);
        // 同样完成调用执行
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        // 照例进行清除
        currentRegistryProcessors.clear();

该步骤是来处理剩下的、未进行排序的postProcessor,该步骤和上面的1.2、1.3有所不同,此处使用了一个循环,原因在于BeanDefinitionRegistryPostProcessor中定义的规范:void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry), 通过参数registry可以实现动态的BeanDefinition的注册,因此只要实现BeanDefinitionRegistryPostProcessor接口,就可以实现新的BeanDefinition的注册。而新注册的这个类,也可能实现了BeanDefinitionRegistryPostProcessor接口,因此,这里需要循环获取,直到找不到为止。在文末,会赋上一个例子,方便理解。

  • 步骤1.5 该步骤只有两行代码,即调用了所有实现BeanFactory的postProcessBeanFactory()方法,源码如下
	invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
	invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
  • 第一个逻辑块总结
  • 遍历方法的第二个参数,找到BeanDefinitionRegistryPostProcessor的实现类,并完成由该接口定义的方法postProcessBeanDefinitionRegistry(registry); 剩下的实例, 为BeanFactoryPostProcessor的实现类, 存入集合
  • 找出所有的BeanDefinitionRegistryPostProcessor、且实现了PriorityOrdered接口的类, 并 "处理"
  • 找出剩下的BeanDefinitionRegistryPostProcessor、且实现了Ordered接口的类, 并"处理"
  • 循环找出剩下的所有的BeanDefinitionRegistryPostProcessor的类, 并"处理
  • 最后, 在调用父类BeanFactoryPostProcessor的方法postProcessBeanFactory(...)
  • 这里的每一个步骤中的 "处理", 主要操作指的是:排序、调用子接口中的postProcessBeanDefinitionRegistry()方法

第二块

  • 步骤2.1 ~ 步骤2.3 由于这三步与第一块处理方式基本一致,且要简单很多,这里我简单进行说明。源码如下。
    // 第二块:
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    List<String> orderedPostProcessorNames = new ArrayList<>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();

    for (String ppName : postProcessorNames) {
        if (processedBeans.contains(ppName)) {		
        } 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);
        }
    }

    // 步骤2.1 BeanFactoryPostProcessor && priorityOrdered
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);


    // 步骤2.2 BeanFactoryPostProcessor && 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);


    // 步骤2.3 BeanFactoryPostProcessor && 无序
    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
    for (String postProcessorName : nonOrderedPostProcessorNames) {
        nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
  • 这里将获取的对象从 BeanDefinitionRegistryPostProcessor 变为了 BeanFactoryPostProcessor,其他的处理方式都是按照 PriorityOrderedOrderednonOrdered 这个顺序进行了处理。
  • invokeBeanFactoryPostProcessors(..):由于这里的对象为BeanFactoryPostProcessor, 所以这个方法调用即为postProcessBeanFactory() 方法

总结

我们用一张图总结这个方法。

文末

前面提到了为什么在步骤1.4处,需要用循环获取,这里给出一个实例。

说明:XXXXX01方法中,以代码的方式动态注册了一个XXXXX02类型的实例:bb,并且XXXXX02这个类也实现了接口BeanDefinitionRegistryPostProcessor。

说明:XXXXX01和XXXXX02都实现了BeanDefinitionRegistryPostProcessor。在XXXXX01方法中注册了一个BeanDefinition:bb, 类型为XXXXX02,而类XXXXX02也是一个BeanDefinitionRegistryPostProcessor实现类。当我们在获取到。正如上面所说:策略增强器的方法中注册的类,又是一个实现了该增强器的类,那就需要再次获取了,所以是不是明白为什么需要循环获取了?

public class MyBeanDefinitionRegistryPostProcessor01 implements BeanDefinitionRegistryPostProcessor {
	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
    	// 通过该方法注册一个实例, 且注册的实例又实现了BeanDefinitionRegistryPostProcessor接口
		GenericBeanDefinition definition = new GenericBeanDefinition();
		definition.setBeanClass(MyBeanDefinitionRegistryPostProcessor02.class);
		registry.registerBeanDefinition("bb", definition);
	}
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
	}
}

public class MyBeanDefinitionRegistryPostProcessor02 implements BeanDefinitionRegistryPostProcessor {
	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
		// 仍然可以通过registry再次注册一个BeanDefinition
	}
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
	}
}

spring.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
	<bean id="myBeanDefinitionRegistryPostProcessor01" class="xxx.xxx.MyBeanDefinitionRegistryPostProcessor01" />
</beans>

测试类:
public class App {

	public static void main(String[] args) {

		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring.xml");

		MyBeanDefinitionRegistryPostProcessor01 bean01 = context.getBean(MyBeanDefinitionRegistryPostProcessor01.class);

		MyBeanDefinitionRegistryPostProcessor02 bean02 = (MyBeanDefinitionRegistryPostProcessor02) context.getBean("bb");

		System.out.println(bean01);

		System.out.println(bean02);
	}
}