本节主要记录BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor的方法执行时机以及简单原理分析。
BeanFactoryPostProcessor
根据注释我们了解到postProcessBeanFactory方法的执行时机为:BeanFactory标准初始化之后,所有的Bean定义已经被加载,但Bean的实例还没被创建(不包括BeanFactoryPostProcessor类型)。该方法通常用于修改bean的定义,Bean的属性值等,甚至可以在此快速初始化Bean。
下面测试一波。
新建SpringBoot项目,Boot版本2.4.0,依赖如下:
1 2 3 4 | <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> |
然后新建MyBeanFactoryPostProcessor,实现BeanFactoryPostProcessor接口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | @Component public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { private static final Logger logger = LoggerFactory.getLogger(MyBeanFactoryPostProcessor.class); public MyBeanFactoryPostProcessor() { logger.info("实例化MyBeanFactoryPostProcessor Bean"); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { int beanDefinitionCount = beanFactory.getBeanDefinitionCount(); logger.info("Bean定义个数: " + beanDefinitionCount); } @Component static class TestBean { public TestBean() { logger.info("实例化TestBean"); } } } |
在postProcessBeanFactory方法内,我们打印了当前已加载Bean定义的个数,并且在MyBeanFactoryPostProcessor类中,注册了TestBean。MyBeanFactoryPostProcessor和TestBean的构造函数输出的日志用于观察Bean实例化时机。
启动程序,输出如下:
上面的日志证实了方法的执行时机的确是在BeanFactory标准初始化之后,所有的Bean定义已经被加载,但Bean的实例还没被创建(此时TestBean还未被实例化,日志还没有输出”实例化TestBean”,但这不包括BeanFactoryPostProcessor类型Bean,该方法执行之前,日志就已经输出了”实例化MyBeanFactoryPostProcessor Bean”)。
我们在postProcessBeanFactory方法上打个断点:
以debug方式启动程序:
通过追踪方法调用栈,我们可以总结出BeanFactoryPostProcessor的postProcessBeanFactory方法执行时机和原理:
-
SpringApplication.run(MyApplication.class, args)
启动Boot程序: -
run
方法内部调用refreshContext
方法刷新上下文: -
refresh
方法内部调用invokeBeanFactoryPostProcessors
方法: -
PostProcessorRegistrationDelegate的
invokeBeanFactoryPostProcessors
方法内部:
BeanDefinitionRegistryPostProcessor
BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProcessor,新增了一个postProcessBeanDefinitionRegistry方法:
通过注释我们了解到postProcessBeanDefinitionRegistry方法的执行时机为:所有的Bean定义即将被加载,但Bean的实例还没被创建时。也就是说,BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法执行时机先于BeanFactoryPostProcessor的postProcessBeanFactory方法。这个方法通常用于给IOC容器添加额外的组件。
举个例子测试一波。
新建BeanDefinitionRegistryPostProcessor的实现类MyBeanDefinitionRegistryPostProcessor:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | @Component public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { private final Logger logger = LoggerFactory.getLogger(MyBeanDefinitionRegistryPostProcessor.class); @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { int beanDefinitionCount = registry.getBeanDefinitionCount(); logger.info("Bean定义个数: " + beanDefinitionCount); // 添加一个新的Bean定义 RootBeanDefinition definition = new RootBeanDefinition(Object.class); registry.registerBeanDefinition("hello", definition); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { } } |
启动程序,输出如下:
可以看到,BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法执行时机的确先于BeanFactoryPostProcessor的postProcessBeanFactory方法。
通过查看PostProcessorRegistrationDelegate的invokeBeanFactoryPostProcessors
方法源码也可以证实这一点:
转自:深入理解BeanFactoryPostProcessor & BeanDefinitionRegistryPostProcessor | MrBird