【精读】你知道Spring中BeanFactoryPostProcessors是如何执行的吗?

了解了BeanDefinition以及生命周期的大概概念以后,咱们班能够试着看一下源码!咱们上一章也说到,BeanFactoryPostProcessors的执行时机是:在扫描完成以后,实例化以前! 那么咱们看一下Spring是如何去回调BeanFactoryPostProcessors的呢?java

org.springframework.context.support.AbstractApplicationContext#refresh
org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors
org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors
    
invokeBeanFactoryPostProcessors就是扫描项目转换成BeanDefinition 而后回调BeanFactoryPostProcessors的地方!咱们看源码也是从这里开始看!
复制代码

我这里会分段截取代码进行讲解,文章末尾会复制整段代码:程序员

代码一:初始化对应的集合

image-20200908091328833

进入到这个方法以后,spring

  1. 咱们会迎来第一个判断,也就是判断当前使用的工厂是否是BeanDefinitionRegistry,这个判断99%都会返回为true,为何呢?由于除非进行了很深度的扩展Spring,本身继承整个工厂的顶级接口AliasRegistry去实现一个彻底由本身实现的工厂,这个判断才会被跳过!这个对于咱们现阶段来讲,不用太过深究,咱们如今就先认定一件事,咱们使用的beanFactory工厂必定是 BeanDefinitionRegistry类型的,这个判断也必定会进来;
  2. 初始化了二个集合,这二个集合各有用意,第一个集合就存放咱们手动提供给Spring的后置处理器,注意这个手动,他并非又Spring扫描获得的,而是咱们本身设置进去的,固然这里是后话!
  3. 第二个集合是存放执行过程当中找到的BeanDefinitionRegistryPostProcessor,为何要存放他呢?由于他是BeanFactoryPostProcessor的子类,在整个执行调用过程当中,咱们会先执行BeanDefinitionRegistryPostProcessor类型的后置处理器,在执行BeanFactoryPostProcessor类型的,可是由于是子类和父类的关系,为了不后面重复的获取,就索性吧BeanDefinitionRegistryPostProcessor存储起来,等待BeanDefinitionRegistryPostProcessor的方法执行完毕以后,就直接执行他父类的方法,这也可以从侧面证实BeanDefinitionRegistryPostProcessorpostProcessBeanFactory方法是优先于BeanFactoryPostProcessorpostProcessBeanFactory方法先执行的!固然这一点我会在后面用代码进行验证!

代码2、遍历用户本身手动添加的后置处理器

image-20200908092446476

这个循环是为了循环程序员本身手动添加的后置处理器(不用太过深究,后面我会用代码说明),若是是BeanDefinitionRegistryPostProcessor的就先调用了,若是是BeanFactoryPostProcessor类型的,就先放到regularPostProcessors集合中,等待BeanDefinitionRegistryPostProcessor执行完毕后,在进行BeanFactoryPostProcessor的调用!缓存

代码三:开始调用实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor

image-20200908093030287

咱们迎来了第一段比较重要的代码,首先会先去在整个bean工厂寻找BeanDefinitionRegistryPostProcessor类型的而且实现了类PriorityOrdered的类!注意此时没有任何人向beanFactory中放置该类型的类,他只有一个实现,就是Spring在开天辟地的时候初始化的几个BeanDefinition,其中有一个符合条件markdown

image-20200908093912603

他就是ConfigurationClassPostProcessor,这个类是Spring初始化的时候就放置到容器里面的,他作的事情很很简单,就是解析Spring配置类,而后扫描项目,将项目内符合条件的类,好比@Server、@Bean之流加了注解的类,转换成BeanDefinition,而后存放到容器,请注意一点,此时通过ConfigurationClassPostProcessor的执行以后,咱们Spring容器中有值了,有了咱们配置的全部的应该被Spring管理的类!此时再去寻找就会寻找咱们本身定义的一些后置处理器了!post

代码四:开始调用实现了Ordered接口的BeanDefinitionRegistryPostProcessor

image-20200908094511381

这一段代码基本和上面的代码同样,惟一不一样的就是本次寻找的是实现了Ordered了的接口,由于上面ConfigurationClassPostProcessor的执行,此时容器内部就又了咱们本身定义的类信息,因此若是咱们有一个类实现了BeanDefinitionRegistryPostProcessor且实现了Ordered接口,那么此时就可以被执行了!学习

代码五:开始调用剩余的BeanDefinitionRegistryPostProcessor

image-20200908101810906

通过上面两个实现了PriorityOrderedOrdered接口两种BeanDefinitionRegistryPostProcessor以后,优先级别最高的已经执行完毕了,后续只须要去执行剩余的BeanDefinitionRegistryPostProcessor就能够了,可是有些读者可能会很疑惑,上面两种调用的都是一个循环就完事了,可是为何这里须要一个死循环呢?spa

由于,BeanDefinitionRegistryPostProcessor是一个接口,在回调他的方法的时候,里面的方法可能又注册了一些BeanDefinition,这些BeanDefinition也是BeanDefinitionRegistryPostProcessor类型的,举个例子就像俄罗斯套娃同样,每个里面都会进行一些注册,谁也不知道会进行套多少层,故而要进行一个死循环,只要有,就一直遍历寻找,直到执行完为止!相似于下图这样:debug

image-20200908095928070

代码六:开始调用BeanDefinitionRegistryPostProcessor的父类方法

image-20200908101909970

  • 第一行代码的意思是执行BeanDefinitionRegistryPostProcessor的父类方法,也就是BeanFactoryPostProcessor的回到方法,由于BeanDefinitionRegistryPostProcessorBeanFactoryPostProcessor类型的,为了不重复查询就实现执行了,他的优先级高于普通的BeanFactoryPostProcessor!
  • 第二行代码的意思是,执行用户手动添加的BeanFactoryPostProcessor!后面说!

代码七:开始寻找BeanFactoryPostProcessor

image-20200908103447903

这个代码逻辑不难看懂code

  1. 先寻找全部的BeanFactoryPostProcessor
  2. 初始化三个集合,实现PriorityOrdered的集合、实现了Ordered的集合、剩余的BeanFactoryPostProcessor集合
  3. 遍历寻找到的全部的BeanFactoryPostProcessor
  4. 判断当 processedBeans集合已经存在,也就是被BeanDefinitionRegistryPostProcessor处理过的直接跳过,避免重复执行!
  5. 若是是实现了PriorityOrdered接口,直接getBean()提早实例化后,加入到对应的集合,注意此时已经进行实例化!
  6. 若是是实现了Ordered接口,那么吧他的名字放到对应的集合中,注意此时他没有实例化!
  7. 将普通的BeanFactoryPostProcessor放到对应的集合,注意也没有实例化!

经过上述,咱们知道了一件事,只有PriorityOrdered类型的BeanFactoryPostProcessor被实例化了,而后放置到了集合中去!

代码八:开始执行BeanFactoryPostProcessor

image-20200908102912853

  • 咱们先对实现了PriorityOrdered的集合进行排序后执行,注意,由于上面在添加到集合的时候已经经过igetBean()实例化了,因此,此时能够直接执行!
  • 遍历实现了Ordered的beanName集合,而后经过getBean,实例化对应的BeanFactoryPostProcessor,放到对应的集合orderedPostProcessors,排序后进行执行!
  • 遍历剩余的BeanFactoryPostProcessor,而后getBean实例化后,直接执行!

代码流程图

4576

完整的代码:

/** * 扫描项目 * 调用BeanDefinitionRegistryPostProcessor 将对应的类转成BeanDefinition * 调用 BeanFactoryPostProcessors的回调方法 * @param beanFactory bean工厂 * @param beanFactoryPostProcessors 手动提供的后置处理器 */
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

    // 若是有的话,首先调用BeanDefinitionRegistryPostProcessors。
    Set<String> processedBeans = new HashSet<>();
    //默认使用的是DefaultListableBeanFactory工厂对象 因此i这个判断必定会进入进来
    if (beanFactory instanceof BeanDefinitionRegistry) {
        //事实上就是Bean工厂
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
        //存放程序员本身手动提供给Spring的后置处理器
        List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
        //存放执行该过程当中寻找到的 BeanDefinitionRegistryPostProcessor
        List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

        //循环遍历bean工厂后处理器 可是这个的debug的对象确实为Null不知道为何 事实上它并不会进入到这里
        //这个是扫描用户本身手动添加的一些BeanFactoryPostProcessors
        //事实上 咱们不多会对这里进行更改,只有在对接或者开发第三方组件的时候可能会手动的设置一个后置处理器
        //正常状况下极少可以使用到这种状况
        for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
            //这个判断就是为了保证spring本身的扫描处理器先执行 由于此时spring尚未完成扫描
            if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor;
                registryProcessor.postProcessBeanDefinitionRegistry(registry);
                registryProcessors.add(registryProcessor);
            }
            else {
                //本身定义的内助处理器
                regularPostProcessors.add(postProcessor);
            }
        }

        // 不要在这里初始化FactoryBeans:咱们须要保留全部常规bean
        // 未初始化,让Bean工厂后处理器对其应用!
        // 在实现的BeanDefinitionRegistryPostProcessor之间分开
        // PriorityOrdered,Ordered和其余。
        List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

        // 首先,调用实现PriorityOrdered(排序接口)的BeanDefinitionRegistryPostProcessors。 这是获取内置bean工厂后置处理器的beanName
        //查出全部实现了BeanDefinitionRegistryPostProcessor接口的bean名称
        //调用了一次BeanDefinitionRegistryPostProcessor子类 PriorityOrdered
        //获取 BeanDefinitionRegistryPostProcessor 的子类 事实上 这里只有一个叫作 ConfigurationClassPostProcessor 他实现了 PriorityOrdered接口
        //BeanFactoryPostProcessor 也就是 ConfigurationClassPostProcessor 会被添加到容器里面
        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            //判断当前这个类是否是实现了PriorityOrdered接口
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                //getBean会提早走生命周期
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                //将这个已经处理过的添加到集合里面
                //为何要天机哀悼集合里面呢?由于自己他就属于 BeanDefinitionRegistryPostProcessor 是 BeanFactoryPostProcessor的子类
                //那么确定 在执行BeanFactoryPostProcessor的回调的时候,他还会再次的被获取执行
                //索性 Spring为了节省效率,避免这部分 BeanDefinitionRegistryPostProcessor类被重复 获取,就在彻底调用了BeanDefinitionRegistryPostProcessor类以后
                //将这一部分的接口直接给执行了也就是BeanDefinitionRegistryPostProcessor的BeanFactoryPostProcessor的回调方法是优先于直接实现BeanFactoryPostProcessor方法的
                //既然在执行BeanFactoryPostProcessor以前就执行了对应的方法回调,那么确定,执行BeanFactoryPostProcessor的时候要把以前已经执行过的过滤掉
                //故而会将BeanDefinitionRegistryPostProcessor存储起来,后续执行BeanFactoryPostProcessor会跳过集合里面的类
                processedBeans.add(ppName);
            }
        }
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        //见该处理器添加到对应的已注册集合里面 方面后面直接回调他们的父类方法也就是 BeanFactoryPostProcessors方法
        registryProcessors.addAll(currentRegistryProcessors);
        //调用Bean定义注册表后处理器 这里是真正的读取类的bd的一个方法 ConfigurationClassPostProcessor 第一次调用beanFactory 后置处理器
        //这里调用ConfigurationClassPostProcessor后置处理器会注册一个后置处理器,下面进行回调
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        //清空当前这个处理器
        currentRegistryProcessors.clear();

        // 接下来,调用实现Ordered的BeanDefinitionRegistryPostProcessors。 Ordered
        postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            //判断当前这个类是否是实现了Ordered接口
            if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                //getBean会提早走生命周期
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        //见该处理器添加到对应的已注册集合里面 方面后面直接回调他们的父类方法也就是 BeanFactoryPostProcessors方法
        registryProcessors.addAll(currentRegistryProcessors);
        //调用当前的BeanDefinitionRegistryPostProcessor 回调方法
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        //清空当前这个处理器
        currentRegistryProcessors.clear();

        // 最后,调用全部其余BeanDefinitionRegistryPostProcessor,直到没有其余的出现。
        boolean reiterate = true;
        //这里为何是死循环呢?
        //由于 BeanDefinitionRegistryPostProcessor 自己进行回调的时候会手动注册一些特殊的类,例如再次注册一个BeanDefinitionRegistryPostProcessor
        //类,可能手动注册的类里面还有,像套娃同样,故而须要进行不断的循环迭代获取,从而达到遍历所有的 BeanDefinitionRegistryPostProcessor的目的
        while (reiterate) {
            reiterate = false;
            //获取全部的BeanDefinitionRegistryPostProcessor接口的实现类
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            //遍历这些BeanDefinitionRegistryPostProcessor类
            for (String ppName : postProcessorNames) {
                //若是它不存在与这个集合里面,证实没有被上面处理过,就不会被跳过,这里主要是解决重复执行的状况
                if (!processedBeans.contains(ppName)) {
                    //添加到对应的当前处理器集合里面
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    //添加到已处理集合里面
                    processedBeans.add(ppName);
                    //将扫描标识为true 准备下次执行
                    reiterate = true;
                }
            }
            //排序
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            //注册到注册集合里面,便于后修直接回调父类
            registryProcessors.addAll(currentRegistryProcessors);
            //开始执行这些方法
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            //清空本次执行的处理集合
            currentRegistryProcessors.clear();
        }

        // 如今,调用到目前为止已处理的全部处理器的postProcessBeanFactory回调。
        //BeanDefinitionRegistryPostProcessor 是 BeanFactoryPostProcessor
        //目的就是为了不重复获取
        invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
        //常规的 普通的工厂后置处理器
        //程序员手动提供给Spring的BeanFactory beanFactory.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor())
        invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    } else {
        // 调用在上下文实例中注册的工厂处理器。
        invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    }

    // 不要在这里初始化FactoryBeans:咱们须要保留全部常规bean
    // 未初始化,让Bean工厂后处理器对其应用!
    //这里是真正获取容器内部全部的beanFactory的后置处理器
    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)) {
            // skip - already processed in first phase above
        }
        //添加 实现了PriorityOrdered的BeanFactoryPostProcessors
        else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
        }
        //添加 实现了Ordered的BeanFactoryPostProcessors
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
        }
        else {
            //添加剩余的
            nonOrderedPostProcessorNames.add(ppName);
        }
    }

    // 首先,调用实现PriorityOrdered的BeanFactoryPostProcessors。
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    //首先回调实现了PriorityOrdered的BeanFactoryPostProcessors
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

    // 接下来,调用实现Ordered的BeanFactoryPostProcessors。
    List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
    for (String postProcessorName : orderedPostProcessorNames) {
        //getBean能够进行提早实例化进入生命周期
        orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    // 接下来,调用实现Ordered的BeanFactoryPostProcessors。
    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

    //最后,调用全部其余BeanFactoryPostProcessors。
    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
    for (String postProcessorName : nonOrderedPostProcessorNames) {
        //getBean能够进行提早实例化进入生命周期
        nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    //这里执行的自定义的bean工厂的后置处理器
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

    // 清除缓存的合并bean定义,由于后处理器可能具备修改了原始元数据,例如替换值中的占位符...
    beanFactory.clearMetadataCache();
}
复制代码

才疏学浅,若是文章中理解有误,欢迎大佬们私聊指正!欢迎关注做者的公众号,一块儿进步,一块儿学习! 欢迎关注做者

相关文章
相关标签/搜索