Springboot扩展点之BeanDefinitionRegistryPostProcessor,你学会了吗?( 二 )

单元测试
@Testpublic void test(){AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.fanfu");Dog dog = ((Dog) context.getBean("dog"));System.out.println(dog.getName());System.out.println(dog.getColor());}UML类图通过BeanDefinitionRegistryPostProcessorUML类图可以看出BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor,postProcessBeanDefinitionRegistry()方法属于BeanDefinitionRegistryPostProcessor,postProcessBeanFactory()属于BeanFactoryPostProcessor,所有实现了BeanDefinitionRegistryPostProcessor接口的实现类都需要实现这个方法,而作为Springboot的扩展点之一,其扩展的逻辑也在这两个方法中;

Springboot扩展点之BeanDefinitionRegistryPostProcessor,你学会了吗?

文章插图
初始化和执行时机通过自定义的MyBeanDefinitionRegistryPostProcessor类,实现BeanDefinitionRegistryPostProcessor接口,从项目启动开始,其执行过程如下:
  1. 执行项目的主类,SpringApplication#run被调用;
  2. 进入boot.SpringApplication#run方法后,刚开始是一些Spring容器初始化的配置操作,直到执行到SpringApplication#refreshContext,开始容器刷新,进入了关键阶段;
  3. 在SpringApplication#refreshContext , 实际的刷新逻辑是在AbstractApplicationContext#refresh方法中;
  4. AbstractApplicationContext#refresh方法中,调用AbstractApplicationContext#invokeBeanFactoryPostProcessors开始初始化和执行实现BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry()和postProcessBeanFactory();
  5. 进入AbstractApplicationContext#invokeBeanFactoryPostProcessors方法 , 发现又调用了PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors();
  6. 在PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()方法中,并不是直接就初始化和执行postProcessBeanDefinitionRegistry()和postProcessBeanFactory(),而是又进行了一系列的判断 , 其判断顺序是:1、通过AbstractApplicationContext#addBeanFactoryPostProcessor提前注册的BeanDefinitionRegistryPostProcessor实现类;2、实现了PriorityOrdered接口;3、是否实现了Ordered;4、剩下的其他BeanDefinitionRegistryPostProcessor实现类;自定义的MyBeanDefinitionRegistryPostProcessor就属于第4类,所以是所有实现里较晚才被执行的,如果想要提前被执行,可以考虑前面三种方式;
  7. 在PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()方法中执行完MyBeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry方法后,紧接着就开始执行MyBeanDefinitionRegistryPostProcessor#postProcessBeanFactory方法了;从整个调用过程看postProcessBeanDefinitionRegistry()是早于postProcessBeanFactory()方法执行;
下面是我根据整个调用过程画的一个时序图 , 过程确实比较复杂,但是逻辑比较清晰,因此并不难理解 , 想要真的搞清楚整个过程,最好的方法就是照着这个图,亲自执行一遍 , 通过debug观察每一个关键节点的执行过程 。
Springboot扩展点之BeanDefinitionRegistryPostProcessor,你学会了吗?

文章插图
内部实现类spring-boot-starter-web中内置的实现类有CachingMetadataReaderFactoryPostProcessor、ConfigurationClassPostProcessor、ConfigurationWarningsPostProcessor、EmbeddedDataSourceBeanFactoryPostProcessor、ImportsCleanupPostProcessor、TestRestTemplateRegistrar、WebTestClientRegistrar、WsdlDefinitionBeanFactoryPostProcessor,观察一下每个实现类会发现:都比较类似,这些内置实现类都是Springboot中的内部类 , 通过这些BeanDefinitionRegistryPostProcessor内部实现类向Spring容器中注册了一些特殊的BeanDefinition,如果展开详细再说一说这些Bean,怕是一天一夜也说不完,有兴趣的小伙伴可以深入了解一下 , 这里就不再展开了 。
总结通过梳理整个过程,其实最关键的就是一句话:在Spring容器初始后、未刷新前,即Bean已被扫描注册为BeanDefinition后 , 未正式实例化前,可以通过实现BeanDefinitionRegistryPostProcessor做一些额外的操作 。

【Springboot扩展点之BeanDefinitionRegistryPostProcessor,你学会了吗?】


推荐阅读