单元测试
@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的扩展点之一,其扩展的逻辑也在这两个方法中;

文章插图
初始化和执行时机通过自定义的MyBeanDefinitionRegistryPostProcessor类,实现BeanDefinitionRegistryPostProcessor接口,从项目启动开始,其执行过程如下:
- 执行项目的主类,SpringApplication#run被调用;
- 进入boot.SpringApplication#run方法后,刚开始是一些Spring容器初始化的配置操作,直到执行到SpringApplication#refreshContext,开始容器刷新,进入了关键阶段;
- 在SpringApplication#refreshContext , 实际的刷新逻辑是在AbstractApplicationContext#refresh方法中;
- AbstractApplicationContext#refresh方法中,调用AbstractApplicationContext#invokeBeanFactoryPostProcessors开始初始化和执行实现BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry()和postProcessBeanFactory();
- 进入AbstractApplicationContext#invokeBeanFactoryPostProcessors方法 , 发现又调用了PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors();
- 在PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()方法中,并不是直接就初始化和执行postProcessBeanDefinitionRegistry()和postProcessBeanFactory(),而是又进行了一系列的判断 , 其判断顺序是:1、通过AbstractApplicationContext#addBeanFactoryPostProcessor提前注册的BeanDefinitionRegistryPostProcessor实现类;2、实现了PriorityOrdered接口;3、是否实现了Ordered;4、剩下的其他BeanDefinitionRegistryPostProcessor实现类;自定义的MyBeanDefinitionRegistryPostProcessor就属于第4类,所以是所有实现里较晚才被执行的,如果想要提前被执行,可以考虑前面三种方式;
- 在PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()方法中执行完MyBeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry方法后,紧接着就开始执行MyBeanDefinitionRegistryPostProcessor#postProcessBeanFactory方法了;从整个调用过程看postProcessBeanDefinitionRegistry()是早于postProcessBeanFactory()方法执行;

文章插图
内部实现类spring-boot-starter-web中内置的实现类有CachingMetadataReaderFactoryPostProcessor、ConfigurationClassPostProcessor、ConfigurationWarningsPostProcessor、EmbeddedDataSourceBeanFactoryPostProcessor、ImportsCleanupPostProcessor、TestRestTemplateRegistrar、WebTestClientRegistrar、WsdlDefinitionBeanFactoryPostProcessor,观察一下每个实现类会发现:都比较类似,这些内置实现类都是Springboot中的内部类 , 通过这些BeanDefinitionRegistryPostProcessor内部实现类向Spring容器中注册了一些特殊的BeanDefinition,如果展开详细再说一说这些Bean,怕是一天一夜也说不完,有兴趣的小伙伴可以深入了解一下 , 这里就不再展开了 。
总结通过梳理整个过程,其实最关键的就是一句话:在Spring容器初始后、未刷新前,即Bean已被扫描注册为BeanDefinition后 , 未正式实例化前,可以通过实现BeanDefinitionRegistryPostProcessor做一些额外的操作 。
【Springboot扩展点之BeanDefinitionRegistryPostProcessor,你学会了吗?】
推荐阅读
- wps文档的扩展名是什么
- 九个AI增强开发效率的VSCode扩展插件
- Spring Event 业务解耦神器,大大提高可扩展性,刷爆了!
- 子时是几点钟,子时是几点到几点之间
- 电脑扩展屏幕能咋的操作
- 电脑应该咋才能扩展屏幕,双屏只能扩展不能复制屏幕
- SpringBoot整合ElasticSearch详解及相关使用方法
- 利用Docker简化机器学习应用程序的部署和可扩展性
- 电脑扩展屏幕能咋样操作
- Springboot之把外部依赖包纳入Spring容器管理的两种方式
