专栏首页程序员备忘录SpringBoot源码学习(五)

SpringBoot源码学习(五)

在之前的学习中,我们大概的学习了springBoot的初始化。大概得流程是springApplication读取通过读取spring.factories文件中SpringBootAppliationinitlizer和springApplicationRunabaleListenner相关的接口。其中listenner伴随着SpringBoot应用启动的全过程,在每个阶段运行结束的时候都会将IOC容器传入并通知所有的listenner对象,其中ConfigFileApplicationListener在SpringApplication类中就开始对配置进行解析。而在IOC初始化结束,praperContent阶段,调用this.applyInitializers(context)的时候就将解析注解的和配置的后置处理器(实现了BeanDefinitionRegistryPostProcessor得类)全部已经注册到beanFactory中的后置处理器map中,之后通过load方法将启动类加载到beanFactory中。这一切都准备好之后,进入SpringBoot的核心启动类中。在核心类中,首先做一些准备工作包括一些容器属性通过配置文件的新值覆盖等。之后获取实现了BeanDefinitionRegistryPostProcessor接口的类进行后置处理。先进行排序,找到优先级比较高的配置解析类等。然后使用先前parperContent中applyInitializers注册的ConfigurationClassPostProcessor进行注解的解析,通过这个后置处理器的处理所有的类都注册到beanDefinitionMap中。之后通过实现了BeanDefinitionRegistryPostProcessor和Order具有排序的接口,逐个调用

postProcessBeanDefinitionRegistry进行处理。

最后逐个获取beanDefinitionMap中实现了BeanDefinitionRegistryPostProcessor接口的类再去轮询调用postProcessBeanDefinitionRegistry方法。

处理完毕之后再使用相同的方法获取实现了BeanFactoryPostProcessor接口的类,还是按照优先级、排序和beanDefinitionMap注册的顺序依次调用postProcessBeanFactory方法。其实经过上述的过程,spring的主体过程已经结束了。剩下的部分就是过去bean的一些bean后置处理。现在让我们继续之前剩下的事业吧!

首先明确一下我们今天分析的焦点,如图所示:

从字面上理解,这个registerBeanPostProcessors就是注册bean的后置处理器。我们之前BeanFactoryPostProcessors是beanFactory的后置处理器。因为他们哪些方法都是在bean工厂初始化之后调用的。那么显然这里的registr就是要将bean实例化之后的一些处理的通用类注册进来。那么必然包括从spring.factories和已经加载到beanDefinitionMap的两部分类。那么这个register就是将这两者按照顺序注册的。然后再bean实例化中逐个去调用。当然这只是我们的猜测。具体是怎么样的?让我们拭目以待。

  protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
  }
  public static void registerBeanPostProcessors(
    ConfigurableListableBeanFactory beanFactory,
     AbstractApplicationContext applicationContext) {
    //获取目前存在于beanDefinitionMap中的bean后置处理器【这里有6个】
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    //将bena的后置处理器添加到beanPostProcessor中
    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
    //具有优先级的bean后置处理器
    List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
    //具有顺序的bean后置处理器
    List<String> orderedPostProcessorNames = new ArrayList<>();
    //一般的bean后置处理器
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    for (String ppName : postProcessorNames) {
      if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        //具有优先级后置处理器添加
        priorityOrderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
          //添加实现了MergedBeanDefinitionPostProcessor接口的后置处理器 
          internalPostProcessors.add(pp);
        }
      }
      else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
        //具有顺序的bean后置处理器
        orderedPostProcessorNames.add(ppName);
      }
      else {
      //无序的后置处理器
        nonOrderedPostProcessorNames.add(ppName);
      }
    }

    //排序
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    //注册进去
    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

    //注册实现了Ordered接口的bean后置处理器
    List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
    for (String ppName : orderedPostProcessorNames) {
      BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
      //添加到list
      orderedPostProcessors.add(pp);
      if (pp instanceof MergedBeanDefinitionPostProcessor) {
      //添加MergedBeanDefinitionPostProcessor接口的bean
        internalPostProcessors.add(pp);
      }
    }
    //排序
    sortPostProcessors(orderedPostProcessors, beanFactory);
    //注册进去
    registerBeanPostProcessors(beanFactory, orderedPostProcessors);
    // 无序的bean后置处理器
    List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
    for (String ppName : nonOrderedPostProcessorNames) {
      BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
      nonOrderedPostProcessors.add(pp);
      if (pp instanceof MergedBeanDefinitionPostProcessor) {
        internalPostProcessors.add(pp);
      }
    }
    //注册无序的
    registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
    //注册MergedBeanDefinitionPostProcessor接口的
    sortPostProcessors(internalPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, internalPostProcessors);
    //在添加一个后置处理器
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
  }

通过上述分析,registerBeanPostProcessors方法就是添加一批bean的初始化之后的后置处理器。

本文分享自微信公众号 - 程序员备忘录(gh_a84f9a607848),作者:tianjl

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-09-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • spring源码(八)

    通过之前的学习我们大致上已经知道了SpringBoot启动的流程。到目前剩下的就是如何将BeanDefineMap中的类转化为真实的bean,然后注册到bean...

    程序员_备忘录
  • python邮件发送和图片

    ​ 上班时间干别的事情是不太好的,如果被别人看到的话会很大程度上影响个人的前进的步伐。但是如果工作做的差不多了,那么闲着也是闲着。反正cpu资源浪...

    程序员_备忘录
  • CyclicBarrier 源码解析

    和CountDownLatch一样,CyclicBarrier也是猜不出其作用,看来和栅栏有关系,哈哈哈

    程序员_备忘录
  • Python数据类型详解-字符串#学习猿地

    # vars = '岁月是把杀猪刀,\n\n但是它拿长得丑的人一点办法都没有。。。'

    学习猿地
  • Python数据类型详解-字符串#学习猿地

    # vars = '岁月是把杀猪刀,\n\n但是它拿长得丑的人一点办法都没有。。。'

    学习猿地
  • Cloudera Enterprise 6 Beta发布

    Fayson
  • 慢性疼痛的脑影像分析

    慢性疼痛是引起全球致残率与保险与医疗法律案件中慢性疼痛相关索赔的重要原因。脑影像(fMRI、PET、EEG及MEG)对于慢性疼痛患者诊断、预后评估、治疗效果评价...

    用户1279583
  • 基于影像学和定量感觉测试预测慢性疼痛的治疗结果

    尽管有许多疗法可以有效地控制某些人的慢性疼痛,如何为所有遭受慢性疼痛的人提供缓解疼痛的方法仍有很大的需求。目前所用的“一刀切”的方法既耗时又昂贵,而且在许多情况...

    用户1279583
  • 关于通信知识的思维导图

    图的左侧,是通信的基本背景知识。图的右侧,我按照云、管、端,把通信整个系统做了梳理。

    鲜枣课堂
  • 不就是装个系统吗?其实我也会的!

    前几天有些粉丝留言说 出一遍教装系统的文章,今天特地写一遍,希望能给大家带来帮助!

    Rookie

扫码关注云+社区

领取腾讯云代金券