Spring源码解析之BeanFactoryPostProcessor(三)

时间:2022-09-30 20:26:25

在上一章中笔者介绍了refresh()的<1>处是如何获取beanFactory对象,下面我们要来学习refresh()方法的<2>处是如何调用invokeBeanFactoryPostProcessors方法执行bean工厂后置处理器,这个方法在笔者看来是整个refresh()方法最重要的方法之一,因为就是在这个方法完成了扫描类路径下所有的类,并将类解析成BeanDefinition注册到spring容器中。

public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
……
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
……
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();//<1>
……
try {
……
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);//<2>
……
} catch (BeansException ex) {
……
} finally {
……
}
}
}
……
}

  

在了解invokeBeanFactoryPostProcessors(beanFactory)方法的运作原理前,我们需要对spring的两个接口有一个基本的认识:BeanFactoryPostProcessor(bean工厂后置处理器)、BeanDefinitionRegistryPostProcessor(bean定义注册后置处理器)。

public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
} public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}

  

如果有看过笔者先前写的Spring源码解析之BeanFactoryPostProcessor(一)应该对BeanFactoryPostProcessor有印象,在这一章节中笔者说过BeanFactoryPostProcessor接口实现类的执行时机是在扫描完所有BeanDefinition并注册到spring容器之后,以及实例化bean之前。这一章笔者也创建了一个BeanFactoryPostProcessor接口的实现类Test1BeanFactoryPostProcessor,在postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)方法中笔者将userService的beanDefinition的class替换成OrderService.class,当我们从spring容器获取userService对应的bean,bean的类型为OrderService而不是UserService。

那么笔者不禁有个疑问,spring又是如何根据程序员指定的类路径将路径下的类解析成BeanDefinition并注册进spring容器呢?答案就在BeanDefinitionRegistryPostProcessor。根据spring官方文档介绍:BeanDefinitionRegistryPostProcessor接口的作用就是向spring容器注册BeanDefinition,且BeanDefinitionRegistryPostProcessor的执行时机在BeanFactoryPostProcessor之前,而BeanFactoryPostProcessor的作用更倾向于在spring容器获取到所有BeanDefinition后,在实例化bean之前,修改BeanDefinition的属性。比如设定连接池的最大连接数不能超过1000,我们就可以在BeanFactoryPostProcessor获取连接池BeanDefinition的最大连接数,如果超过一千则将最大连接数改为1000。又或者我们提供了一个聊天服务接口ChatService,并实现了一个与之同名的实现类,假设这个实现类是基于MySQL实现的一个聊天服务,后续我们又开发了一个基于Redis的聊天服务实现类ChatService2,当外部需要依赖注入ChatService接口时我们更希望注入的是基于Redis实现的ChatService2聊天服务而不是原先基于MySQL实现的ChatService,也可以实现一个BeanFactoryPostProcessor,并将chatService的BeanDefinition的class替换成ChatService2。

Spring源码解析之BeanFactoryPostProcessor(一)讲述AnnotatedBeanDefinitionReader的时候,笔者曾说过这个类的构造方法会执行到AnnotationConfigUtils.registerAnnotationConfigProcessors(...),在这个方法内会注册一些基础组件的BeanDefinition注册进spring容器中。当时笔者说过其中一个基础组件:ConfigurationClassPostProcessor就是完成BeanDefinition扫描的工作,而ConfigurationClassPostProcessor这个类就实现了BeanDefinitionRegistryPostProcessor,在postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)方法中扫描出配置类指定路径下所有的类,并筛选出那些可以成为BeanDefinition的类注册到spring容器中。

此外,BeanDefinitionRegistryPostProcessor的父类是BeanFactoryPostProcessor,从某个角度上来看:BeanDefinitionRegistryPostProcessor接口的实现也可以看作是BeanFactoryPostProcessor。因此refresh()方法中调用的invokeBeanFactoryPostProcessors(beanFactory),除了执行BeanFactoryPostProcessor的实现类,还会执行BeanDefinitionRegistryPostProcessor的实现类,而且BeanDefinitionRegistryPostProcessor实现类的执行时机会先于BeanFactoryPostProcessor的实现类。

当调用invokeBeanFactoryPostProcessors(beanFactory)方法时,会进而执行到PostProcessorRegistrationDelegate类的静态方法invokeBeanFactoryPostProcessors(...),这个方法接收一个beanFactory和BeanFactoryPostProcessor列表。

在下面的代码<1>处,会先判断传入的beanFactory对象能否转型成BeanDefinitionRegistry,在Spring源码解析之BeanFactoryPostProcessor(二)章节中笔者曾介绍这针对注解(AnnotationConfigApplicationContext)和XML(ClassPathXmlApplicationContext)应用上下文spring各开发了两个父类GenericApplicationContext和AbstractRefreshableApplicationContext来获取beanFactory,这两个父类的beanFactory对象类型为DefaultListableBeanFactory,DefaultListableBeanFactory类既是ConfigurableListableBeanFactory接口的实现类,也是BeanDefinitionRegistry接口的实现类,所以大部分情况下会进入<1>处的分支。因为通常我们启动spring容器不是通过注解就是通过XML初始化应用上下文,而注解和XML应用上下文返回的beanFactory类型实际上都是DefaultListableBeanFactory,除非是重写refreshBeanFactory()、获取getBeanFactory()这两个方法,那么可以自定义一个BeanFactory的实现类且不实现ConfigurableListableBeanFactory接口,也就不会进到分支<1>。

在进入到<1>处的分支后会循环beanFactoryPostProcessors列表,如果列表内的元素可以转型成BeanDefinitionRegistryPostProcessor,则执行元素实现的的postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)方法,将元素添加到registryProcessors列表,如果不能转型则添加到regularPostProcessors列表,到达一定时机,spring会执行registryProcessors和regularPostProcessors两个列表中元素实现的postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)。这里也印证了spring官方文档所说的BeanDefinitionRegistryPostProcessor实现类会优先于BeanFactoryPostProcessor实现类执行。

此外,这里我们也注意到参数beanFactoryPostProcessors是由AbstractApplicationContext调用getBeanFactoryPostProcessors()方法传入的,getBeanFactoryPostProcessors()会返回beanFactoryPostProcessors这个列表,beanFactoryPostProcessors默认为一个空列表,我们可以调用addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor)将自己创建的bean工厂后置处理器对象添加到beanFactoryPostProcessors这个列表。因此,在执行invokeBeanFactoryPostProcessors(...)最初会先执行由程序员创建的BeanDefinitionRegistryPostProcessor对象。

public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
……
private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors = new ArrayList<>();
……
@Override
public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor) {
Assert.notNull(postProcessor, "BeanFactoryPostProcessor must not be null");
this.beanFactoryPostProcessors.add(postProcessor);
}
public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {
return this.beanFactoryPostProcessors;
}
……
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
……
}
……
} final class PostProcessorRegistrationDelegate {
……
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { // Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>(); if (beanFactory instanceof BeanDefinitionRegistry) {//<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);
}
}
……
} else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
……
}
……
}

  

这里我们创建一个bean工厂后置处理器(BeanFactoryPostProcessor)和BeanDefinition注册后置处理器(BeanDefinitionRegistryPostProcessor)的实现类,并创建者两个类的实例添加到上下文对象然后看看两个实现类实现的接口的回调时机。

Test3BeanDefinitionRegistryPostProcessor.java

package org.example.beanFactoryPostProcessor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; public class Test2BeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("test2 postProcessBeanFactory...");
}
}

 

Test3BeanDefinitionRegistryPostProcessor.java 

package org.example.beanFactoryPostProcessor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; public class Test3BeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
System.out.println("test3 postProcessBeanDefinitionRegistry...");
} @Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("test3 postProcessBeanFactory...");
}
}

  

测试用例:

    @Test
public void test05() {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
ac.addBeanFactoryPostProcessor(new Test2BeanFactoryPostProcessor());
ac.addBeanFactoryPostProcessor(new Test3BeanDefinitionRegistryPostProcessor());
ac.refresh();
}

  

打印结果:

test3 postProcessBeanDefinitionRegistry...
test3 postProcessBeanFactory...
test2 postProcessBeanFactory...

  

可以看到spring会优先执行BeanDefinitionRegistryPostProcessor实现类的postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)方法,再执行BeanDefinitionRegistryPostProcessor实现类的postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)方法,最后才执行BeanFactoryPostProcessor实现类的postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)方法。

需要注意一点的是:spring有两种提供bean工厂后置处理器(BeanFactoryPostProcessor )的方式:

  1. 创建一个bean工厂后置处理器对象并调用addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor)将对象添加到spring容器*spring回调。
  2. 编写一个BeanFactoryPostProcessor的实现类,并且给类标记上@Component注解,spring会获取实现了BeanFactoryPostProcessor接口的类,并生成bean调用其接口,比如前面笔者所编写的Test1BeanFactoryPostProcessor。

这两种方式不同点是:前者是程序员手动创建bean工厂后置处理器对象再交由spring执行,但这个对象本身不是一个bean,这个对象虽然实现了spring的接口,但它的生命周期不归spring管理;后者是bean工厂后置处理器对象的创建由spring负责,这个对象在spring容器中是一个bean,spring同样会这个bean的回调方法,这个bean的生命周期由spring管理。

上面这两种提供方式同样适用于BeanDefinition注册后置处理器(BeanDefinitionRegistryPostProcessor),因为BeanDefinitionRegistryPostProcessor本身就可以看成是一个BeanDefinitionRegistryPostProcessor。

标记了@Component注解的BeanFactoryPostProcessor实现类,它的bean对象不在AbstractApplicationContext类的beanFactoryPostProcessors列表中。换句话说beanFactoryPostProcessors列表的元素必须手动创建对象并添加,假设我们开发了两个BeanDefinitionRegistryPostProcessor的实现类:FooBeanDefinitionRegistryPostProcessor和BarBeanDefinitionRegistryPostProcessor,FooBeanDefinitionRegistryPostProcessor是用过手动创建对象添加到beanFactoryPostProcessors列表,BarBeanDefinitionRegistryPostProcessor是通过@Component注解由spring创建bean对象。下面代码<1>处遍历beanFactoryPostProcessors列表中只有一个FooBeanDefinitionRegistryPostProcessor对象会得到执行,而BarBeanDefinitionRegistryPostProcessor对应的bean会在后面的代码进行接口回调,但不会在<1>处进行回调。

final class PostProcessorRegistrationDelegate {
……
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { // Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>(); if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>(); for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {//<1>
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
……
}
……
}
……
}

  

我们来对比下下面18~29、32~42这两段代码,这两段代码完成的工作是极其相似的,会遍历所有已经注册到spring容器的BeanDefinition,找出BeanDefinitionRegistryPostProcessor实现类对应的beanName并将其返回。之后会在<1>、<2>处判断这个beanName对应的class在实现了BeanDefinitionRegistryPostProcessor接口的前提下,是否分别实现了PriorityOrdered、Ordered接口。

Ordered是PriorityOrdered的父接口,PriorityOrdered本身并没有实现任何方法,而是直接继承Ordered,实现了PriorityOrdered的类会优先于实现了Ordered的类执行。Ordered接口会要求实现类返回一个数值用于排序,返回数值越小的实现类排在越前。之后这两段代码都会从bean工厂根据beanName和类型获取BeanDefinitionRegistryPostProcessor实现类的bean对象,并将待执行的bean对象加到currentRegistryProcessors列表,将对应的beanName加入到processedBeans表示已经处理这个bean,再对currentRegistryProcessors列表进行排序,这里就会用到Ordered接口要求返回的数值,越小排越前,即返回数值越小越优先执行。

排序完毕后会将currentRegistryProcessors列表的元素加入到registryProcessors列表,然后调用invokeBeanDefinitionRegistryPostProcessors(...)方法遍历currentRegistryProcessors列表每个对象,执行其实现的postProcessBeanDefinitionRegistry(...)方法,开始真正处理列表中每一个bean对象,处理完毕后再清空currentRegistryProcessors列表。而registryProcessors列表在未来的某个时机,会执行列表中所有对象实现的postProcessBeanFactory(...)方法。

需要注意一点:第一段代码会找出所有实现了BeanDefinitionRegistryPostProcessor和PriorityOrdered接口的实现类,将其beanName加入到processedBeans表示这个bean已经处理,即便这个时候尚未执行bean对象的postProcessBeanDefinitionRegistry(...)方法,但后续会执行。第二段代码在找出BeanDefinitionRegistryPostProcessor和Ordered接口实现类的同事,也会找到第一段代码已经找到的实现类,因为PriorityOrdered是Ordered的子接口,意味着实现了PriorityOrdered同样实现了Ordered,但这里不会出现重复执行同一个bean对象的的postProcessBeanDefinitionRegistry(...)方法,因为在第二段代码会再判断beanName是否在processedBeans中,只有不在processedBeans集合的beanName才允许执行,如果beanName已经在processedBeans,表明这个bean在之前已经执行了postProcessBeanDefinitionRegistry(...)方法。currentRegistryProcessors列表在这两段代码都只会存放尚未执行的BeanDefinitionRegistryPostProcessor实现类,并且在这两段代码执行完毕后都会清空currentRegistryProcessors列表,所以我们也不用担心registryProcessors列表会存在相同的bean对象。

这里还可以和大家先剧透一下,先前我们介绍的在构造AnnotatedBeanDefinitionReader对象时会将一些基础组件以BeanDefinition的形式注册到spring容器中待后续spring容器根据BeanDefinition构造bean,其中一个基础组件ConfigurationClassPostProcessor就会在下面第一段代码(即18~29行)执行,ConfigurationClassPostProcessor为BeanDefinitionRegistryPostProcessor和PriorityOrdered两个接口的实现类,在执行这个实现类的postProcessBeanDefinitionRegistry(...)方法时,就会扫描配置类指定的类路径,并筛选类路径下可以成为BeanDefinition的类注册进spring容器,供后续spring根据BeanDefinition构造bean。ConfigurationClassPostProcessor是如何完成BeanDefinition的筛选和注册后续笔者还会讲解,这里我们只要知道第一段代码会完成类路径的扫描即可。

final class PostProcessorRegistrationDelegate {
……
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { // Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>(); if (beanFactory instanceof BeanDefinitionRegistry) {
……
// 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<BeanDefinitionRegistryPostProcessor> 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)) {//<1>
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)) {//<2>
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
……
}
……
}
……
}

  

BeanDefinitionRegistryPostProcessor接口是spring较为底层的接口,spring-context包下也只有ConfigurationClassPostProcessor实现了BeanDefinitionRegistryPostProcessor接口,除了ConfigurationClassPostProcessor类之外spring家族再无BeanDefinitionRegistryPostProcessor接口的实现。此外就笔者目前所见的开源框架,除了spring-context、spring-boot外,也只有mybatis集成spring的包(mybatis-spring)实现了BeanDefinitionRegistryPostProcessor接口,即:org.mybatis.spring.mapper.MapperScannerConfigurer,不过MapperScannerConfigurer类并没有实现PriorityOrdered和Ordered的接口,所以MapperScannerConfigurer并不会再上面的代码执行,而是会在后续的某个时机执行。

在先后执行完实现了PriorityOrdered和Ordered接口的BeanDefinitionRegistryPostProcessor实现类,会用一个while循环不断从bean工厂获取尚未执行的BeanDefinitionRegistryPostProcessor实现类,因为可能存在spring在执行一个BeanDefinitionRegistryPostProcessor实现类的postProcessBeanDefinitionRegistry(...)方法时有新的BeanDefinitionRegistryPostProcessor类以BeanDefinition的形式注册进bean工厂。每次循环都会把尚未执行的BeanDefinitionRegistryPostProcessor实现类加入到registryProcessors列表,直到获取不到尚未执行的BeanDefinitionRegistryPostProcessor实现类才会退出循环,而我们之前所说的MapperScannerConfigurer类也就是在下面的while循环执行的,退出while循环后统一执行registryProcessors和regularPostProcessors列表中对象实现的postProcessBeanFactory(...)。

已经找到整个项目中所有的BeanDefinitionRegistryPostProcessor对象,这个列表的顺序会优先存储程序员手动创建的BeanDefinitionRegistryPostProcessor对象,再存储实现了PriorityOrdered和Ordered接口的BeanDefinitionRegistryPostProcessor对象,,不管是内置的亦或是集成别的项目或是程序员自己开发的BeanDefinitionRegistryPostProcessor实现类,都会存到,和regularPostProcessors两个列表中对象实现的postProcessBeanFactory(...)方法。

final class PostProcessorRegistrationDelegate {
……
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { // Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();

if (beanFactory instanceof BeanDefinitionRegistry) {
……
// 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);
}
……
}
……
}

  

如果beanFactory可以转型成BeanDefinitionRegistry,则会进入分支<1>,而在分支<1>内部会做的工作我们也已经了解。如果beanFactory不能转型成BeanDefinitionRegistry,则会进入分支<2>,这里就会执行我们手动创建的BeanFactoryPostProcessor对象的postProcessBeanFactory(...)方法。但就笔者目前的开发经验,大部分情况下都会进入分支<1>,会进入分支<2>的情况笔者至今还未见过,希望有这方面业务经验的同学可以不吝赐教。

在执行分支<1>或分支<2>的代码后,会获取spring容器内所有BeanFactoryPostProcessor实现类对应的beanName,这里依旧可能把之前已经处理过的beanName获取出来。在遍历这些beanName的时候如果判断已经在processedBeans集合中,则表示已经处理过,这里就会跳过这个beanName,如果是不在processedBeans集合,则会根据是否实现PriorityOrdered、Ordered接口和都没实现分为三组,会分别对实现了PriorityOrdered和Ordered接口的bean工厂处理器进行排序,再分组执行,最后执行没有实现PriorityOrdered和Ordered接口的bean工厂后置处理器。

final class PostProcessorRegistrationDelegate {
……
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { // Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>(); if (beanFactory instanceof BeanDefinitionRegistry) {//<1>
……
} else {//<2>
// 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<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();
}
……
}

  

下面我们来看看PriorityOrdered和Ordered两个接口,正如笔者所言, PriorityOrdered接口本身并没有要求实现任何方法,PriorityOrdered接口的设计只是为了和Ordered做一个区分,子接口会优先执行,父接口会在子接口执行完毕后才执行。这两个接口都会要求实现类在getOrder()方法返回一个数值,数值越小排序越前。

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

  

最后,我们总结下PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(...)整个方法的流程就结束本章的讲解。这个方法接收一个beanFactory对象,和beanFactoryPostProcessors列表。通常情况下:beanFactoryPostProcessors列表是程序员手动创建的BeanFactoryPostProcessor对象,beanFactory可以转型成BeanDefinitionRegistry,所以会进入下面代码<1>处的分支。在分支<1>内部会创建两个列表regularPostProcessors和registryProcessors,这里会遍历beanFactoryPostProcessors列表,判断列表中每个对象是否能转型成BeanDefinitionRegistryPostProcessor接口,如果转型成功则执行其实现的postProcessBeanDefinitionRegistry(...)方法并将对象存放到registryProcessors列表,转型失败则存放在regularPostProcessors列表。

之后在代码的33~44行会获取已经以BeanDefinition形式存放到spring容器内BeanDefinitionRegistryPostProcessor实现类对应的beanName,并判断beanName对应的BeanDefinitionRegistryPostProcessor实现类是否也实现了PriorityOrdered,实现了PriorityOrdered接口则会进入<2>处的分支,从bean工厂根据beanName获取对应的bean对象并加入到currentRegistryProcessors列表,之后会将currentRegistryProcessors列表进行排序,将列表中的元素添加到registryProcessors,执行currentRegistryProcessors列表所有对象实现的postProcessBeanDefinitionRegistry(...)方法,再清空currentRegistryProcessors列表。而在33~44行也会执行BeanDefinitionRegistryPostProcessor的实现类ConfigurationClassPostProcessor,在这个实现类的postProcessBeanDefinitionRegistry(...)方法中完成类路径的扫描,解析类路径下可以成为BeanDefinition的类并将其注册到spring容器中。

代码47~57行和33~44太过相似,不同的是后者执行的是同样实现了Ordered接口的BeanDefinitionRegistryPostProcessor实现类,由于PriorityOrdered是Ordered的子接口,这里会把33~44行已经执行过的beanName找出来,但这些已经执行过的beanName已经存放在processedBeans集合,所以这里会过滤掉,只会执行尚未执行的Ordered和BeanDefinitionRegistryPostProcessor的实现类。

在代码<4>处会有一个while循环,不断去遍历spring容器内现有BeanDefinitionRegistryPostProcessor实现类对应的beanName,这里同样会把之前已经找到的beanName获取出来,同样会用processedBeans集合过滤已经处理过的beanName,只会执行尚未执行的BeanDefinitionRegistryPostProcessor实现类的bean对象。等到确定spring容器内不再有尚未执行的BeanDefinitionRegistryPostProcessor实现类就会退出while循环。此时registryProcessors已经拥有了程序员手动创建的BeanDefinitionRegistryPostProcessor对象和整个spring容器所有的BeanDefinitionRegistryPostProcessor实现类的bean对象,在<5>处会执行这些BeanDefinitionRegistryPostProcessor对象的postProcessBeanFactory(...)方法,再执行程序员手动创建的BeanFactoryPostProcessor对象的postProcessBeanFactory(...)方法,至此完成分支<1>的所有工作,所有的BeanDefinitionRegistryPostProcessor对象都先后完成了postProcessBeanDefinitionRegistry(...)和postProcessBeanFactory(...)方法的调用。

之后会获取spring容器内所有BeanFactoryPostProcessor实现类对应的beanName,这里会遍历这些beanName,如果已经存在processedBeans集合的beanName代表已经处理过,这里会跳过已经处理过的beanName,收集实现了PriorityOrdered或Ordered接口,和这两个接口都没实现的BeanFactoryPostProcessor实现类的bean对象,这里会优先对实现了PriorityOrdered接口的BeanFactoryPostProcessor对象进行排序并执行postProcessBeanFactory(...)方法,再对实现了Ordered接口的BeanFactoryPostProcessor对象进行排序再执行postProcessBeanFactory(...)方法,最后是执行没有实现PriorityOrdered或Ordered接口的BeanFactoryPostProcessor对象的postProcessBeanFactory(...)方法。

这里也再次证实了spring对BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor两个接口的定义:BeanDefinitionRegistryPostProcessor的实现会优先于BeanFactoryPostProcessor执行,而BeanDefinitionRegistryPostProcessor实现的postProcessBeanDefinitionRegistry(...)也会优先本身实现的postProcessBeanFactory(...)执行,最后才执行仅实现了BeanFactoryPostProcessor接口的postProcessBeanFactory(...)方法。

final class PostProcessorRegistrationDelegate {
……
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { // Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>(); if (beanFactory instanceof BeanDefinitionRegistry) {//<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);
}
} // 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<BeanDefinitionRegistryPostProcessor> 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)) {//<2>
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)) {//<3>
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) {//<4>
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);//<5>
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<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();
}
……
}

  

Spring源码解析之BeanFactoryPostProcessor(三)的更多相关文章

  1. Spring源码解析之BeanFactoryPostProcessor(一)

    BeanFactoryPostProcessor 在前面几个章节,笔者有介绍过BeanFactoryPostProcessor,在spring在解析BeanDefinition之后,正式初始化bean ...

  2. Spring源码解析之BeanFactoryPostProcessor(二)

    上一章,我们介绍了在AnnotationConfigApplicationContext初始化的时候,会创建AnnotatedBeanDefinitionReader和ClassPathBeanDef ...

  3. Spring源码解析之ConfigurationClassPostProcessor(二)

    上一个章节,笔者向大家介绍了spring是如何来过滤配置类的,下面我们来看看在过滤出配置类后,spring是如何来解析配置类的.首先过滤出来的配置类会存放在configCandidates列表, 在代 ...

  4. Spring源码解读之BeanFactoryPostProcessor的处理

    前言 前段时间旁听了某课堂两节Spring源码解析课,刚好最近自己又在重新学习中,便在这里记录一下学习所得.我之前写过一篇博文,是介绍BeanFactoryPostProcessor跟BeanPost ...

  5. Spring源码解析 - AbstractBeanFactory 实现接口与父类分析

    我们先来看类图吧: 除了BeanFactory这一支的接口,AbstractBeanFactory主要实现了AliasRegistry和SingletonBeanRegistry接口. 这边主要提供了 ...

  6. spring 源码解析

    1. [文件] spring源码.txt ~ 15B     下载(167) ? 1 springн┤┬вио╬Ш: 2. [文件] spring源码分析之AOP.txt ~ 15KB     下载( ...

  7. Spring源码解析——循环依赖的解决方案

    一.前言 承接<Spring源码解析--创建bean>.<Spring源码解析--创建bean的实例>,我们今天接着聊聊,循环依赖的解决方案,即创建bean的ObjectFac ...

  8. Spring源码解析系列汇总

    相信我,你会收藏这篇文章的 本篇文章是这段时间撸出来的Spring源码解析系列文章的汇总,总共包含以下专题.喜欢的同学可以收藏起来以备不时之需 SpringIOC源码解析(上) 本篇文章搭建了IOC源 ...

  9. Spring源码分析之&grave;BeanFactoryPostProcessor&grave;调用过程

    前文传送门: Spring源码分析之预启动流程 Spring源码分析之BeanFactory体系结构 本文内容: AbstractApplicationContext#refresh前部分的一点小内容 ...

随机推荐

  1. Bitmap文件格式&plus;生成一个BMP文件

    Bitmap的文件格式: #define UINT16 unsigned short #define DWORD unsigned int #define WORD short #define LON ...

  2. testng依赖,顺序,跳过

    依赖测试@test(dependsOnMethods = {"open"})@testpublic static void open{    System.out.println( ...

  3. JPA 系列教程11-复合主键-2个&commat;Id

    复合主键 指多个主键联合形成一个主键组合 需求产生 比如航线一般是由出发地及目的地确定,如果要确定唯一的航线就可以用出发地和目的地一起来表示 ddl语句 CREATE TABLE `t_airline ...

  4. MySQL存储汉字

    之前在网上查找了很多方法,排在前排的都是修改配置文件my.ini的,没有成功,后来找到了一个解决方法: 在建表的时候,在语句后面加上段"engine = innodb default cha ...

  5. 轻松理解 Spark 的 aggregate 方法

    2019-04-20 关键字: Spark 的 agrregate 作用.Scala 的 aggregate 是什么 Spark 编程中的 aggregate 方法还是比较常用的.本篇文章站在初学者的 ...

  6. PHP浮点数的精确计算BCMath

    Php: BCMath bc是Binary Calculator的缩写.bc*函数的参数都是操作数加上一个可选的 [int scale],比如string bcadd(string $left_ope ...

  7. axios中的qs

    qs是一个npm仓库所管理的包,可通过npm install qs命令进行安装. 1. qs.parse()将URL解析成对象的形式 const Qs = require('qs'); let url ...

  8. halocn&sol;C&plus;&plus; &lpar;第一篇&rpar;

        在使用C++编写halcon之前,确定自己有较好的C++基础,并熟悉一套开发平台如VC   Programmers_guide.pdf chapter7中有关于creating Aplicat ...

  9. Freemarker自定义方法

    在项目中有一个需求,每个物品有一个guid,存在数据库中,而在页面上需要显示一个对应的业务数据值,暂且叫做serverId,serverId是通过guid移位计算得来.serverId只需要显示,后台 ...

  10. spring aop切面编程实现操作日志步骤

    1.在spring-mvc.xml配置文件中打开切面开关: <aop:aspectj-autoproxy proxy-target-class="true"/> 注意: ...