invokeBeanFactoryPostProcessors(beanFactory); 重点!

171 阅读19分钟

invokeBeanFactoryPostProcessors(beanFactory); 重点!

/**
 * Instantiate and invoke all registered BeanFactoryPostProcessor beans,
 * respecting explicit order if given.
 * <p>Must be called before singleton instantiation.
 */
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    // invokeBeanFactoryPostProcessors方法需要提供两个参数:
    // 1.其中一个是beanFactory,原因是需要获取到当前的beanFactory中的各种Postprocessor执行回调
    // 2.第二个参数getBeanFactoryPostProcessors():其实是类属性的beanFactoryPostProcessors的获取,他是一个List<BeanFactoryPostProcessor>,装载了各种BeanFactoryPostProcessor的一个集合
    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)
    // 检测 LoadTimeWeaver 并准备编织,如果在此期间找到(例如,通过 ConfigurationClassPostProcessor 注册的@Bean方法)
    if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
}

该方法重点看第10行:invokeBeanFactoryPostProcessors方法需要提供两个参数:

  1. beanFactory:原因是需要获取到当前的beanFactory中的各种Postprocessor执行回调。
  2. getBeanFactoryPostProcessors():其实是类属性的beanFactoryPostProcessors的获取,他是一个List,装载了各种BeanFactoryPostProcessor的一个集合,存的是程序员通过api手动往spring容器中提供的PostProcessor。

那么spring是如何去做扩展的呢?

我们可以看一个案例:

public class AnnotationConfigReaderTest implements BeanDefinitionRegistryPostProcessor {
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		//在这里做一些程序员对BeanFactory的扩展操作...
	}

	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
		//在这里做一些程序员对BeanDefinition的扩展操作...
	}
}

上述代码我们实现了一个叫做BeanDefinitionRegistryPostProcessor的BeanPost Process接口,注意它只是BeanFactoryPostProcessor其中的一个接口:

@FunctionalInterface
public interface BeanFactoryPostProcessor {
	/**
	 * 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 overriding or adding
	 * properties even to eager-initializing beans.
	 * @param beanFactory the bean factory used by the application context
	 * @throws org.springframework.beans.BeansException in case of errors
	 */
	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

其实spring在这里提供各种PostProcessor接口的目的是为了可以叫程序员可以在spring执行Bean初始化动作的时候,让程序员也参与进来,为什么这么说呢?

原因是,我可以从上面的那张spring生命周期的简图中看出,其实spring整体的流程是较为固定,就比如我们的实例化单例Bean,假设spring现在没有在这里给我们提供一些对于Bean示例化的BeanPostProcessor接口,但是我作为程序员想到了一些办法去做了对Bean实例化的时候一些自定义的操作,好了,问题来了!你在这里确确实实是对Bean做了一些额外自定义化的动作,但是问题是我上面说过了,spring的生命周期大致是定死的,至少来,先是准备一个BeanFactory,然后再扫描指定包下的类,然后再合并beanDefinition,然后再校验当前的Bean是否是单例的呀?是否是原型的呀?是否是懒加载的呀?等等等,你看上面的流程基本都是定死的,所以说总结一下:

spring为什么会提供这么多的PostProcessor接口,这里不仅仅是给你提供扩展点,更加深层次的原因,在该执行某些动作的时候,那你的扩展动作也在原来的要执行的地方执行掉!再精简点:在合适的地方做合适的事!
我们上面提到了BeanDefinitionRegistryPostProcessor接口是实现了BeanFactoryPostProcessor接口的,然后在invokeBeanFactoryPostProcessors(beanFactory);中执行,但是问题来了,他们的执行顺序是怎么样的呢?

看到上述的类实现层级图了吗?我们按照BeanFactoryPostProcessor为Y,将实现类BeanDefinitionRegistryPostProcessor为X来验证这个事情。

public class BBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
	//父类:BeanFactoryPostProcessor
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		System.out.println("BY-postProcessBeanFactory");
	}

	//子类:BeanDefinitionRegistryPostProcessor
	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
		System.out.println("BY-postProcessBeanDefinitionRegistry");
	}
}
public class ABeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
	//父类:BeanFactoryPostProcessor
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		System.out.println("AX-postProcessBeanFactory");
	}

	//子类:BeanDefinitionRegistryPostProcessor
	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
		System.out.println("AX-postProcessBeanDefinitionRegistry");
	}
}
public class CBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		System.out.println("CY-postProcessBeanFactory");
	}
}
public class Application {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        //无序的注入三个类
        context.register(
            ABeanDefinitionRegistryPostProcessor.class,
            CBeanFactoryPostProcessor.class,
            BBeanDefinitionRegistryPostProcessor.class
            );
        context.refresh();
    }
}

从上面的执行结果来看,spring对于PostProcessor的执行顺序是:

  1. 先执行子类的回调方法:BeanDefinitionRegistryPostProcessor下的postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)方法。
  2. 然后再去执行子类中实现了BeanFactoryPostProcessor的方法:postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)方法。
  3. 最后再执行直接实现了BeanFactoryPostProcessor接口的类中的postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)方法。

下面我们来开始全面的讲解

invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors)方法:

首先第一行为什么它这里是一个set集合?

我们先将代码看到spring循环处理PostProcessor的地方:

/**
 * 该方法执行所有实现了BeanFactoryPostProcessor接口(包括实现BeanFactoryPostProcessor接口的子接口比如:BeanDefinitionRegistryPostProcessor)的回调工作
 * @param beanFactory
 * @param beanFactoryPostProcessors
 */
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
    /**
     * Invoke BeanDefinitionRegistryPostProcessors first, if any.首先调用 BeanDefinitionRegistryPostProcessor(如果有)。
     * 存放执行完成会调用方法的bean的name
     */
    Set<String> processedBeans = new HashSet<>();
    /**
     * 直接强转为BeanDefinitionRegistry
     */
    if (beanFactory instanceof BeanDefinitionRegistry) {
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
        /**
         * regularPostProcessors:可以看到泛型是BeanFactoryPostProcessor接口,意味着它是用来存放实现了BeanFactoryPostProcessor接口Bean的集合
         */
        List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
        /**
         * registryProcessors:可以看到泛型是BeanDefinitionRegistryPostProcessor接口,意味着它是用来存放实现了BeanDefinitionRegistryPostProcessor接口Bean的集合
         */
        List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
        /**
         * 下面循环执行传入的beanFactoryPostProcessors的postProcessor
         */
        for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
            /*判断如果是BeanDefinitionRegistryPostProcessor*/
            if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                /*就直接强转为BeanDefinitionRegistryPostProcessor*/
                BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor;
                /*执行当前的PostProcessor*/
                registryProcessor.postProcessBeanDefinitionRegistry(registry);
                /*执行完成之后将当前的registryProcessor放入到registryProcessors集合中*/
                registryProcessors.add(registryProcessor);
            }
            else {
                /*否则不是BeanDefinitionRegistryPostProcessor接口类型那么就将他放入到regularPostProcessors集合中*/
                regularPostProcessors.add(postProcessor);
            }
        }

在这里提一个点就是我们spring在循环处理beanFactoryPostProcessors的值其实在上一层的getBeanFactoryPostProcessors()方法传进来的。

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

你会发现很简单,这个beanFactoryPostProcessors就是一个List集合。

做个实验我们在外部填入一些实现了BeanFactoryPostProcessor的类丢进去:

public class Application {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
		//手动向spring容器中丢入需要执行的PostProcessor
		//X--直接实现了BeanFactoryPostProcessor接口的
		context.addBeanFactoryPostProcessor(new CBeanFactoryPostProcessor());
		//Y--直接实现了BeanDefinitionRegistryPostProcessor接口的,间接实现了BeanFactoryPostProcessor接口的
		context.addBeanFactoryPostProcessor(new BBeanDefinitionRegistryPostProcessor());
		context.refresh();
	}
}

然后我们再跑Debug来验证来看刚刚的流程说的对不对:

下面开始对我们刚刚往里面丢的两个Bean进行循环处理,来看看是不是刚刚咱们所说的那个逻辑:

可以看到当前的postProcessor是CBeanFactoryPostProcessor这个类,它是直接实现了BeanFactoryPostProcessor接口的。

再到下一次循环轮到了BBeanDefinitionRegistryPostProcessor它是实现了BeanDefinitionRegistryPostProcessor,所以类型判断之后直接进入到了if代码块中,并且进行了类型的强转,ok上面的截图中我们再次执行一步就会打印我们再实现了BeanDefinitionRegistryPostProcessor接口的方法postProcessBeanDefinitionRegistry()中的内容,看效果:

下面来稍稍的总结一下子,画个图:

然后我们再说一下为什么如果是为什么是BeanDefinitionRegistryPostProcessor类型的执行完回调方法之后还要将他加入到registryProcessors集合?

  1. 该循环中判断是子类比如:BeanDefinitionRegistryPostProcessor,那么它的回调方法被执行完成了,但是父类的也就是BeanFactoryPostProcessor的回调方法还没有被执行呢!
  2. 后续执行到了父类的回调方法,然后依次取出来执行父类中的回调方法。

然后再说为什么是父类BeanFactoryPostProcessor就是add到regularPostProcessors集合呢?

  1. 主要目的是为了实现执行顺序
  2. 虽然他们两个都是为了Bean的回调扩展服务的,但毕竟一个是父类一个是子类
  3. 假如有一天我想要先执行子类中的方法回调方法咋办?换而言之我又想要先执行父类中的方法咋办呢?
  4. 总结一句话:为什么这么做其实是为了做到可以控制PostProcessor的执行顺序(执行时机)

下面再来说,执行完成放入集合的事情后spring做了什么:

List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
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. 我们可以看到的是在第一行创建了一个BeanDefinitionRegistryPostProcessor类型的集合。
  2. 然后再通过beanFactory获取到类型为BeanDefinitionRegistryPostProcessor的postProcessorNames数组。
  3. 将这个postProcessorNames数组进行遍历循环,并且每次循环的时候都进行判断,当前的Bean有没有实现PriorityOrdered接口。
  4. 如果实现了,将当前的Bean通过getBean的方式从beanFactory中拿出来,放到currentRegistryProcessors中,这里提一嘴,去BeanFactory中获取,判断如果获取不到,说明没有它会创建一个放到单例池中,然后再获取,最后再将当前的Bean放入到currentRegistryProcessors集合中。
  5. 但是可以看到的是下面还有一行,processedBeans.add(ppName);,回忆一下这个方法的第一行是不是new了Set processedBeans = new HashSet<>();
  6. 我们当时说这个集合的作用是拿来存放执行完成会调用方法的bean的name,在这里就用到了。
  7. 然后到13行开始对有实现了PriorityOrdered接口的Bean进行排序。
  8. 排序完成将当前排好顺序的currentRegistryProcessors存放到实现了BeanDefinitionRegistryPostProcessor接口Bean的集合registryProcessors中。
  9. 然后再通过第15行的invokeBeanDefinitionRegistryPostProcessors()方法来执行外部自定义的postProcessor方法。
  10. 最后将当前的currentRegistryProcessors清空。

然后我们继续往下看,咦!奇怪怎么和上面的代码差不多的?

// 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();
  1. 是的没错是差不多,但是最大的不是在哪里?
  2. 就是在循环的时候判断的不再是PriorityOrdered接口了,而是Ordered接口。
  3. ok下面的步骤是一模一样的。
  4. 显然我们在这里可以很清晰的看出Spring作者的意图了,其实就是想让spring在执行这些回调方法的时候按照当前实现接口的顺序来执行。
  5. 先是PriorityOrdered接口,然后再是Ordered接口。
  6. spring的作者为什么要这么做呢?
  7. 原因很简单:第一个是想让spring在执行回调方法的时候有顺序的时候执行,第二点是我们要知道spring在执行的回调方法的时候,可能会外部往spring容器中添加其他的后置处理器的情况,要是说你这个时候,没有注意,没有给它执行,这不就是直接注册了和他妈没注册一样吗?说明你spring对外开放的扩展接口不可靠!

TIPS:这里我们稍微说一下这个getBeanNamesForType()方法,该方法十分的复杂,它的作用是你通过Bean的类型,来获取到对应的beanName,大致过程是,先去单例池中找,没有的话,再去BeanDefinitionMap和MergeBeanDefinitionMap中找。这里还要再考虑一点,就是该方法在寻找中的对于目标类的定义是什么样的呢?分为三种情况:

  1. 我的bean的BeanType不属于当前的我想要的BeanType,但是通过它的getBean()或者是getType()返回的BeanType是当前想要的类型的也要返回回来。
  2. 当前想要的BeanType和查找的beanType是一样的那没话说。
  3. 假如当前的Bean本身不会当前的你想要的BeanType但是这个Bean中有一个静态代码的类型是你想要的类型getBeanNamesForType()方法也会给你返回回来。

下面我们再看,在第14行,为什么在执行当前的BeanDefinitionRegistryPostProcessor这些回调方法之后,还需要将当前的currentRegistryProcessors addAll()到registryProcessors中呢?我们来回忆一下

/**
 * Invoke BeanDefinitionRegistryPostProcessors first, if any.首先调用 BeanDefinitionRegistryPostProcessor(如果有)。
 * 存放执行完成会调用方法的bean的name,目的是为了再下一次的遍历中不会重复执行
 */
Set<String> processedBeans = new HashSet<>();

这个processedBeans是拿来干啥的?存放执行完成会调用方法的bean的name,目的是为了再下一次的遍历中不会重复执行,其实它还有一个作用就是,当我实现了BeanDefinitionRegistryPostProcessor的同时,其实我也实现了BeanFactoryPostProcessor,所以它的方法我还没有回调处理呢?咋的你把BeanDefinitionRegistryPostProcessor的回调执行完成之后就把BeanFactoryPostProcessor忘记了?它里面万一用户写了某些逻辑咋办?所以这里为什么需要将执行完成的currentRegistryProcessors addAll()到processedBeans中目的是:当spring某天要执行BeanDefinitionRegistryPostProcessor接口的父类BeanFactoryPostProcessor接口的方法时候方便回调执行

我们现在来讲一下invokeBeanDefinitionRegistryPostProcessors()方法,该方法是整个spring那些骚操作中最重要的方法,当然了当前我们不说它其他的功能就说咱上面说的内容,我们来进行验证:

  1. 首先准备三个类实现了 BeanDefinitionRegistryPostProcessor BeanFactoryPostPorcessor
@Component
public class ABeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
	//父类:BeanFactoryPostProcessor
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		System.out.println("AX-postProcessBeanFactory");
	}

	//子类:BeanDefinitionRegistryPostProcessor
	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
		System.out.println("AX-postProcessBeanDefinitionRegistry");
	}
}
@Component
public class BBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor, Ordered, PriorityOrdered {
	//父类:BeanFactoryPostProcessor
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		System.out.println("BY-postProcessBeanFactory");
	}

	//子类:BeanDefinitionRegistryPostProcessor
	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
		System.out.println("BY-postProcessBeanDefinitionRegistry");
	}

	@Override
	public int getOrder() {
		return 1;
	}
}
@Component
public class CBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		System.out.println("CY-postProcessBeanFactory");
	}
}

并且他们都是添加了@Component注解。

@ComponentScan("com.lukp.beanDefinitionRegistryPostProcessor")
public class Config {
}

添加一个配置类,扫描上面三个类。

public class Application {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
		context.register(Config.class);
		context.refresh();
	}
}

主启动类。

  1. 下面开始一步一步的打断点来看:

往下走:

到这里判断当前的BeanFactory是否是BeanDefinitionRegistry,并且直接进入到代码块中直接强转。

到这一步开始循环的处理实现了beanFactoryPostProcessors接口的回调方法,但是当前是没有的,所以不会进去。

直接跳到了这里创建了一个currentRegistryProcessors集合。

这个时候我们看到在单例池中,只有三个spring内置的三个Bean,系统环境变量,标准环境变量、系统配置。

这个时候找出了org.springframework.context.annotation.internalConfigurationAnnotationProcessor

由于该类实现了BeanDefinitionRegistryPostProcessor接口所以就会被扫描进来了。

然后把它放入到currentRegistryProcessors集合中进行处理。

处理结束之后放入到processedBeans集合中。

ok,下面的这两个方法我们就不看了,不太重要,作用咱也懂,并且现在也只有一个bean咋排序呢?

ok,下面来到今天的重头戏,invokeBeanDefinitionRegistryPostProcessors方法,我们说了这个方法是spring花头的来源,基本spring的花活都来自这里,但是咱们今天只验证,@ComponentScan注解生效的效果。还记得在刚刚我们beanDefinitionMap中只有6个:

并且你看config那个配置类也在其中,就是它加了@ComponentScan注解,所以按照道理来说,只要执行了invokeBeanDefinitionRegistryPostProcessors方法在BeanDefinitionMap中就会多出三个被扫描的Bean,ok看结果:

行,这里我们回过头来说,这个invokeBeanFactoryPostProcessors方法中为什么找了一遍还要找一遍,甚至不够,还搞了一个循环来找,来看看BeanDefinitionRegistryPostProcessor接口。

看见没它的入参都是BeanDefinitionRegistry,先别管他是干啥的,从它的名字至少说明一点它的入参是满足一个bean的注册的,所以也就是说,当你执行完成一次之后,多多少少会有新的bean被注册进来,那么你下面继续遍历继续遍历行吗?为什么他后面的Bean也要实现了一些回调呢?那你不漏了?

好了最后一步就是把当前需要需要执行回调方法的集合清空。

我们接着往下看:

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

上述代码的第一句注释其实就十分明确的和我们说下面它要做什么了,翻译一下:

原文:Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.

译文:最后,调用所有其他beandefintionregistrypostprocessors,直到没有其他的beandefintionregistrypostprocessors为止。

从上述代码我们也可以看到在代码的第一行就设置了一个boolean类型的属性reiterate,为true,这是要让下的成一个死循环呀!

但是我接着往下看,就会发现在在第4行将该参数设置为了false,然后再在下面的循环中判断这个方法一开始的那个集合中是否存在当前要执行回调的ppName,如果判断在processedBeans中没有,说明是可以执行的因为processedBeans集合是存放被执行之后的BeanName,按照这个逻辑下去,只要有一天判断到当前的被执行回调的ppName存在了,就会跳出循环,因为没有进入到if代码块中,也就不会将reiterate变量设置为true。

好的到这里对于BeanDefinitionRegistryPostProcessor接口执行的回调方法有一个小总结:

下面就是把invokeBeanFactoryPostProcessor方法的结尾收一下:

// Do not initialize FactoryBeans here: We need to leave all regular beans uninitialized to let the bean factory post-processors apply to them!
// 不要在这里初始化 FactoryBeans:我们需要让所有常规 bean 未初始化,让 bean Factory 后处理器应用于它们!
/**
 * 1.执行父类的回调(直接实现了父类接口BeanFactoryPostProcessor接口的)。
 * 2.比如扫描得到的。
 * 3.有个问题上面也说执行父类和这里有啥区别,上面的回调处理的是接口实现了BeanFactoryPostProcessor接口的,
 * 4.或者程序员直接通过addBeanFactoryPostProcessor()方法添加的,
 * 5.为什么直接通过该方法添加的执行优先级最高,看看上面的传参其中一个是啥?它将这个集合中实现BeanFactoryPostProcessor接口的放入到regularPostProcessors集合中统一在下面进行回调处理
 * 6.所以这里处理的BeanFactoryPostProcessor和上面有点不太一样,可能是通过扫描进来的
 */
String[] postProcessorNames = beanFactory.getBeanNamesForType(
        BeanFactoryPostProcessor.class,
        true,
        false
);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,Ordered, and the rest.
/**
 * 1.首先创建了一个priorityOrderedPostProcessors集合,用于存放实现了priorityOrdered接口
 * 2.创建了orderedPostProcessorNames用来存放ordered接口
 * 3.创建nonOrderedPostProcessorNames存放啥也没实现的ppName
 * 4.我们看这里的实现和上述差不多,但是也是有区别的,就是它是看在最顶上的那个集合processorBeans是否有我们当前所执行的ppName
 * 5.如果判断到了就直接跳过了:skip - already processed in first phase above
 * 6.否则判断当前所执行的ppName没有被执行过还是和上面的逻辑一样判断实现了啥接口?PriorityOrdered or Ordered
 */
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.
// 首先,调用实现 PriorityOrdered 的 BeanFactoryPostProcessor。
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
// 接下来,调用实现 Ordered 的 BeanFactoryPostProcessor。
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.
// 最后,调用所有其他 BeanFactoryPostProcessor。
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
    nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
//这个方法执行程序员自定义的BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have modified the original metadata, e.g. replacing placeholders in values...
// 清除缓存的合并Bean定义(mergeBDMap)清除allBeanNamesByType缓存,因为后处理器可能已经修改了原始元数据,例如替换值中的占位符......
beanFactory.clearMetadataCache();

注释都已经打在上面了我就不说了其实和上面的没啥区别,但是又有那么点区别,至于区别在上面的注释都有。

但是这里我们说一个问题,上面这个if块中spring的作者为什么没有像下面那样子,给它分出来这么多的list来进行分类,然后最后直接都执行回调动作,回忆一下我们上面的这个if块中,这样子做是不是有一个目的就是为防止你在执行回调的过程中会有新的回调Bean被注入进来,防止漏掉呀!但是下面就不会因为它是执行BeanFactoryPostProcessor接口就不会发生这样子的情况,因为在它接口声明中的参数是ConfigurableListableBeanFactory beanFactory。

我们可以来看看ConfigurableListableBeanFactory类中是没有向spring容器的beanDefinitionMap中注册beanDefinition的方法的:

但是BeanDefinitionRegistryPostProcessor的接口入参BeanDefinitionRegistry registry是有的:

这就解释为什么下面else代码块中可以直接new几个集合来存放对应的Bean,完成回调但是上面的if代码块却不行。

最后再讲一下invokeBeanFactoryPostprocessor方法的最后一行方法:

beanFactory.clearMetadataCache();

简单来说:

  1. 该方法就是为了防止refrash()方法下面的方法获取当前的mergeBeanDefinitionMap的时候获取的不是最新的BD。
  2. 该方法方法的两个作用是:1.提供标识为stale=1,2.更新BD,严格来说是合并BD。

然后我们还要解释一个问题,为什么在下面的esle代码块中只添加BeanName的到对应的集合中呢?

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.
// 首先,调用实现 PriorityOrdered 的 BeanFactoryPostProcessor。
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
// 接下来,调用实现 Ordered 的 BeanFactoryPostProcessor。
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.
// 最后,调用所有其他 BeanFactoryPostProcessor。
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
    nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
//这个方法执行程序员自定义的BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

我们发现它下面是一层一层执行的,先是执行priorityOrderedPostProcessors再执行orderedPostProcessor最后执行nonOrderedPostProcessors。这样子的好处其实和上面的差不多,但是这里有个问题,我们知道BeanFactoryPostProcessor接口与BeanDefinitionRegistryPostProcessor的最大区别是一个可以再回调方法中,搞一个新的BD进来,但是BeanFactoryPostProcessor是没有这样的方法的,但是它有一个方法可以修改BD,好了,那么问题来了,假如我上述代码再扫描结束之后,你通过实现了BeanFactoryPostProcessor接口来改变我了BD,但是我却实例化了,那么你下面对与当前BD的改动其实是不生效的呀!所以spring作者为什么在获取BD的不直接实例化的原因就是这个。那他现在的解决思路也就是,我先获取所有的搞三个集合,每个集合存不同类型的回调方法的name: