这一章要讲一讲,上次打断点的方法。这个方法非常重要,是我们揭开spring源码的必经之路。
AnnotationConfigApplicationContext.refresh().invokeBeanFactoryPostProcessors()
可以看到博主在里面写了一个注释,“执行所有可靠的BeanFactoryPostProcessors”。
想要理解这句话,首先要明白什么是BeanFactoryPostProcessors?
按照字面意思的话,很明显,就是Bean工厂的处理器,执行各种各样对于Bean内容的处理。比如上一章看到beanDefinitionMap中就有处理Bean里面Autowired注解的处理器。
再说另外一个词“可靠”,对于spring来说,什么BeanFactoryPostProcessors是可靠的呢。
有两种方式,一种是被扫描到的,一种是被手动通过Api添加的,在启动的时候都会被执行。
@Component
public class A implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("a-p scan postProcessBeanFactory");
}
}
public class B implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("b-p api parent postProcessBeanFactory");
}
}
@Test
public void defaultContext(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.addBeanFactoryPostProcessor(new B());
context.refresh();
}
我们在实现BeanFactoryPostProcessors一个是通过BeanFactoryPostProcessors这个类。
也可以通过BeanFactoryPostProcessors的子类 BeanDefinitionRegistryPostProcessor来实现。
他们两个都有默认的方法,我们实现的时候必须要重写的。
那么问题就来了,是到底先执行哪个的实现方法?先执行子类的实现,还是先执行父类的实现?
通过扫描和通过Api交给spring的两个类,会先执行哪个?
下面就来根据这些问题写一些测试代码。
/**
* 通过扫描注册
* 继承父类BeanFactoryPostProcessor
*/
@Component
public class A implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("a-p scan postProcessBeanFactory");
}
}
/**
* 通过api注册
* 继承父类BeanFactoryPostProcessor
*/
public class B implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("b-p api parent postProcessBeanFactory");
}
}
/**
* 通过api注册
* 继承子类BeanDefinitionRegistryPostProcessor
*/
public class C implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("c-s api parent postProcessBeanFactory");
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
System.out.println("c-s api subclass postProcessBeanDefinitionRegistry");
}
}
/**
* 通过扫描注册
* 继承子类BeanDefinitionRegistryPostProcessor
* 并且手动通过注册Bean的方法处理了E,F类
*/
@Component
public class D implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("d-s api parent postProcessBeanFactory");
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
System.out.println("d-s api subclass postProcessBeanDefinitionRegistry registry E, F");
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(E.class);
registry.registerBeanDefinition("e", builder.getBeanDefinition());
BeanDefinitionBuilder FBuilder = BeanDefinitionBuilder.genericBeanDefinition(F.class);
registry.registerBeanDefinition("f", FBuilder.getBeanDefinition());
}
}
/**
* 通过BeanDefinition方式注册
* 继承父类BeanFactoryPostProcessor
*/
public class E implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("e-p bd parent postProcessBeanFactory");
}
}
/**
* 通过BeanDefinition方式注册
* 继承子类BeanDefinitionRegistryPostProcessor
*/
public class F implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("f-s bd parent postProcessBeanFactory");
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
System.out.println("f-s bd subclass postProcessBeanDefinitionRegistry");
}
}
/**
* 通过扫描的方式注册
* 继承父类BeanFactoryPostProcessor
* 并且继承了Spring会进行判断的PriorityOrdered
*/
@Component
public class H implements BeanFactoryPostProcessor, PriorityOrdered {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("h-p scan parent postProcessBeanFactory PriorityOrdered");
}
@Override
public int getOrder() {
return 0;
}
}
/**
* 通过扫描的方式注册
* 继承子类BeanDefinitionRegistryPostProcessor
* 并且继承了Spring会进行判断的PriorityOrdered
*/
@Component
public class I implements BeanDefinitionRegistryPostProcessor, PriorityOrdered {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("I-s scan parent postProcessBeanFactory PriorityOrdered");
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
System.out.println("I-s scan subclass postProcessBeanDefinitionRegistry PriorityOrdered");
}
@Override
public int getOrder() {
return 0;
}
}
@Test
public void defaultContext(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.scan("com.spring.context.bfpp");
context.addBeanFactoryPostProcessor(new B());
context.addBeanFactoryPostProcessor(new C());
context.refresh();
}
然后来看这个方法是如何实例化和执行这几个类的,
我把所有这个方法中的代码一行行解析,添加了注释,跟着流程走一步就懂了。
看看[A, B, C, D, E, F, H, I]这些类到底是什么时候执行的父类,什么时候执行的子类
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
//这里保证子类和父类的方法不会重复执行
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();
//在spring源码这里基本就是百分百会进来,beanFactory始终实现了BeanDefinitionRegistry接口
if (beanFactory instanceof BeanDefinitionRegistry) {
//转为BeanDefinitionRegistry是为了后面动态注册BeanDefinition
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
//存储所有实现BeanFactoryPostProcessor的Bean 也就是实现父类的Bean
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
//存储所有实现BeanDefinitionRegistryPostProcessor 的Bean 也就是实现子类的Bean
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
//这里循环需要处理的类,因为这时候还没有执行扫描,前面我们说过这个方法处理完之后才会扫描
// 所以这里面只有 B、C两个类
//只有这两个类是我们通过Api直接塞进来的
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
//判断是否继承了子类BeanDefinitionRegistryPostProcessor
//C会进这里
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
//强转为子类,直接回调了子类的方法,然后进入registryProcessors子类的集合
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
//B类会进这里,没有做任何事情,直接添加进子类的集合
regularPostProcessors.add(postProcessor);
}
}
/**
* 这个时候regularPostProcessors 中有[B]
* registryProcessors 中有[C] 并且C类已经回调了子类的方法
*/
// 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.
//根据类型查询,到beanDefinitionMap中,看有哪些类继承了子类,这里只会找到一个ConfigurationClassPostProcessor
//在初始化beanDefinitionMap的时候只有它继承了子类,上一章讲了初始化时候里面有5个类
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
//判断是否实现了PriorityOrdered接口 这里为true
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
//通过getBean()方法实例化出来ConfigurationClassPostProcessor
//然后放到需要执行的集合中
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
//表示已经处理完了
processedBeans.add(ppName);
}
}
//排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
//合并到子类的集合中,都执行完了为什么要放到子类集合中呢?
//这里回调了子类方法,但是没有执行父类方法,放在这里就是等着未来回调父类方法
registryProcessors.addAll(currentRegistryProcessors);
//遍历回调子类postProcessBeanDefinitionRegistry方法
//方法具体执行的内容,我们一会也会详细讲,这里只需要知道执行了就可以了
//并且执行完ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry()这个方法,就完成了扫描
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
//清空执行集合,留着以后继续用
currentRegistryProcessors.clear();
/**
* 这个时候regularPostProcessors 父类集合 中有[B]
* registryProcessors 中有[C, ConfigurationClassPostProcessor] 并且都已经回调了子类的方法
* processedBeans 处理完成的集合[ConfigurationClassPostProcessor]
* 并且已经完成了扫描
*/
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
//再次从beanDefinitionMap中,获取继承子类的对象,
//因为已经完成了扫描,所以这次可以获取到[currentRegistryProcessors, D, I]
//并且 D:实现了子类,I:实现了子类并且实现了PriorityOrdered
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
//判断是否已经处理过了,上面在处理currentRegistryProcessors的时候把它加进了processedBeans集合中,那么第一次循环的时候不会进去
//第二次循环D类肯定不在,但是没有实现Ordered接口,所以也不会进入这个判断
//第三次循环I类既没有执行过,也实现了Ordered接口,所以会进这个判断
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
//这里也是通过getBean()实例化出I类,并且放入执行集合中
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
//放入已处理完集合
processedBeans.add(ppName);
}
}
//排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
//合并到子类的集合中,等待回调父类
registryProcessors.addAll(currentRegistryProcessors);
//回调子类方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
//清空当前执行集合
currentRegistryProcessors.clear();
/**
* 这个时候regularPostProcessors 父类集合 中有[B]
* registryProcessors 中有[C, ConfigurationClassPostProcessor, I] 并且都已经回调了子类的方法
* processedBeans 处理完成的集合[ConfigurationClassPostProcessor, I]
* 并且已经完成了扫描
*/
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
/**
* 这里通过一个死循环,继续寻找继承了子类的对象,
* 上面已经找过两次了,为什么这里还有死循环找第三次?
* 两个原因:
* 第一是因为子类回调的方法可以动态注册新的BeanDefinitionPostProcessors,这里面的类是扫描不到的,只有回调完子类的方法之后才能发现。
* 第二个原因,在上次找的时候,找到了D和I两个类,但是只执行了I类,D类还没有执行
*
*/
boolean reiterate = true;
while (reiterate) {
reiterate = false;
//第一次死循环,找到[currentRegistryProcessors, D, I]
//第二次死循环,找到[currentRegistryProcessors, D, I, F] , 为什么没有找到E? 因为E实现的是父类
//第三次死循环,找到[currentRegistryProcessors, D, I, F]
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
//第一次死循环,currentRegistryProcessors和 I已经执行了,所以只有D会进去
//第二次死循环,找到[currentRegistryProcessors, D, I, F],只有F会进去,其他都执行过了
//第三次死循环,找到[currentRegistryProcessors, D, I, F],没有可以进去的
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
//找到就放入已执行集合
processedBeans.add(ppName);
//如果找到了,就还需要进行下一次死循环,因为无法保证子类没有注册新的BeanDefinitionPostProcessors,所以就要继续找
reiterate = true;
}
}
//第一次死循环,这里只拿到了D进行处理
//第二次死循环,这里只拿到了F进行处理
//第三次死循环,不会执行这里
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
//第一次死循环,D在执行子类方法的时候,注册了E和F两个类
//第二次死循环,F的子类方法只打印了日志,没有注册新的类
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
/**
* 这个时候regularPostProcessors 父类集合 中有[B]
* registryProcessors 子类集合 中有[C, ConfigurationClassPostProcessor, I, D, F] 并且都已经回调了子类的方法
* processedBeans 处理完成的集合[ConfigurationClassPostProcessor, I, D, F]
* 并且已经完成了扫描
*/
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
//这里是执行registryProcessors继承子类集合中,所有类的父类方法
//registryProcessors 子类集合 中有[C, ConfigurationClassPostProcessor, I, D, F]
//在这里都回调了父类方法
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
//执行父类集合中,所有类的父类方法
//regularPostProcessors 父类集合 中有[B]
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
//这里在spring框架中都不会进来
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
/**
* 这个时候regularPostProcessors 父类集合 中有[B] 已经回调了父类方法
* registryProcessors 子类集合 中有[C, ConfigurationClassPostProcessor, I, D, F] ,并且父类子类方法都已经执行
* processedBeans 处理完成的集合[ConfigurationClassPostProcessor, I, D, F]
* 并且已经完成了扫描
*/
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
//找到所有继承了父类的对象[A, E, H]
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
//存储所有实现了PriorityOrdered接口的父类集合
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
//存储所有实现了Ordered接口的父类集合,需要注意的是priorityOrdered是Ordered的子类,所有进上面那个集合的对象,也会进这个集合
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)) {
//H类会进这里
//为什么只有这里实例化了
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
//A会进入这里
//E也会进入这里
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
//排序
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
//实现了priorityOrdered的优先执行父类方法 H
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
//orderedPostProcessorNames这个为空,所以不会执行
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.
//这里执行了A和E两个对象
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
//实例化
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
//执行H和E的父类方法
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
/**
* 这个时候regularPostProcessors 父类集合 中有[B] 已经回调了父类方法
* registryProcessors 子类集合 中有[C, ConfigurationClassPostProcessor, I, D, F] ,并且父类子类方法都已经执行
* processedBeans 处理完成的集合[ConfigurationClassPostProcessor, I, D, F]
* 并且已经完成了扫描
* priorityOrderedPostProcessors 集合中有[H] 已经回调了父类方法
* nonOrderedPostProcessors 集合中有[A,E] 已经回调了父类方法
*
* 到这里为止,所有继承了父类BeanFactoryPostProcessor和子类BeanDefinitionRegistryPostProcessor的对象都已经处理完毕了,
* 现在明白具体的执行顺序了吧
*
*/
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
//这个方法是相当难的,后面会详细解析
beanFactory.clearMetadataCache();
}
总结:
先处理子类,并且要优先执行实现了PriorityOrdered接口的类
并且先执行通过API注入的C类,
然后是扫描到的继承了PriorityOrdered接口的 “I”类
最后执行扫描到的D类,以及被子类方法注册的F类,中的子类方法
执行所有继承子类的父类方法[C, ConfigurationClassPostProcessor, I, D, F]
执行当前继承子类的父类方法[B]
接着处理父类
扫描所有继承父类的方法,通过注解注入的只有[A, E, H]
先执行继承PriorityOrdered接口的H类
在执行继承Ordered接口的类,无
最后执行A和E的父类方法
问题解析:
为什么子类BeanDefinitionRegistryPostProcessor可以动态注册新的processor而父类BeanFactoryPostProcessor不可以?为什么不开放(不建议使用)这个功能?
答:因为子类会循环调用,一直到所有的注册processor类全都执行完,而父类不会,父类回调方法之后,直接就结束了。
虽然父类确实可以动态注册新的processor,但是新的processor里面需要执行的方法和扫描之类的却不会执行。
为什么实现order接口的先执行getBean()?
答:因为实现了Order接口的类,可以认为比其他类高一级,会先执行类中的方法,有可能会改变其他类,所以要等实现Order接口类执行完成之后,才能实例化其他类。
既然实现子类BeanDefinitionRegistryPostProcessor可以动态注册类,那为什么我们之前手写mybatis的时候,会使用ImportBeanDefinitionRegistrar接口来动态注册mapper呢,两者有什么区别?
答:新版的mybatis中,ImportBeanDefinitionRegistrar实现的接口并没有动态注册mapper,而是动态注册了一个processor,由这个处理器来扫描所有的mapper。(老版的mybatis中ImportBeanDefinitionRegistrar方法直接完成了扫描和注册mapper)
ImportBeanDefinitionRegistrar实现的接口是在优先处理手动注入processor类的时候就会执行了,所以优先级是很高的。
mybatis新版和老版的区别就是
老版ImportBeanDefinitionRegistrar直接扫描和注册mapper
而新版则是在ImportBeanDefinitionRegistrar中注册了processor类,然后通过spring源码里面的执行顺序去完成扫描和注册。
为什么mybatis一定要使用ImportBeanDefinitionRegistrar?
要获取注解中的包路径,如果直接使用processor类的话无法获取。