BeanDefinitionRegistryPostProcessor
是BeanFactoryPostProcessor
的一个子接口
:::info
BeanDefinitionRegistryPostProcessor
调用时机分析
:::
BeanDefinitionRegistryPostProcessor
作为BeanFactoryPostProcessor
的子接口,当用户自定义BeanDefinitionRegistryPostProcessor
的时候,必将同时实现两个方法,postProcessBeanDefinitionRegistry
和父方法postProcessBeanFactory
- 从IOC容器中获取到所有的BeanDefinitionRegistryPostProcessor组件
- 并依次触发它们的postProcessBeanDefinitionRegistry方法
- 然后再来触发它们的postProcessBeanFactory方法
- 再来从IOC容器中获取到所有的BeanFactoryPostProcessor组件,并依次触发它们的postProcessBeanFactory方法
今天我们重点来看BeanDefinitionRegistryPostProcessor
接口的postProcessBeanDefinitionRegistry
方法:
它的参数是BeanDefinitionRegistry,顾名思义就是与BeanDefinition注册相关的。
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
// 注册bean到spring容器中
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
通过观察Spring自动注入类BeanDefinitionRegistry
,我们发现它里边包含了registerBeanDefinition
方法,这个不就是我们想要的吗?
为了能更好的使用该接口来达到注入Bean的目的,我们先来看看Spring是如何操作此接口的。
从invokeBeanFactoryPostProcessors
方法入手,优先执行BeanDefinitionRegistry类型的beanFactory
上述源码依次执行实现了PriorityOrdered
的BeanDefinitionRegistryPostProcessor
和实现了Ordered
的BeanDefinitionRegistryPostProcessor
进入BeanDefinitionRegistryPostProcessor
接口的生效方法invokeBeanDefinitionRegistryPostProcessors
,进一步发现,BeanDefinitionRegistryPostProcessor
类的postProcessBeanDefinitionRegistry
方法会被调用
private static void invokeBeanDefinitionRegistryPostProcessors
(Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry)
{
Iterator var2 = postProcessors.iterator();
while(var2.hasNext()) {
BeanDefinitionRegistryPostProcessor postProcessor = (BeanDefinitionRegistryPostProcessor)var2.next();
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
}
退出invokeBeanDefinitionRegistryPostProcessors
方法,最后执行父接口BeanFactoryPostProcessor
:::info
代码验证
:::
接下来编写测试代码进行验证。编写一个类MyBeanDefinitionRegistryPostProcessor,实现BeanDefinitionRegistryPostProcessor接口
package com.meimeixia.ext;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.stereotype.Component;
import com.meimeixia.bean.Blue;
// 记住,我们这个组件写完之后,一定别忘了给它加在容器中
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// TODO Auto-generated method stub
System.out.println("MyBeanDefinitionRegistryPostProcessor...bean的数量:" + beanFactory.getBeanDefinitionCount());
}
/**
* 这个BeanDefinitionRegistry就是Bean定义信息的保存中心,这个注册中心里面存储了所有的bean定义信息,
* 以后,BeanFactory就是按照BeanDefinitionRegistry里面保存的每一个bean定义信息来创建bean实例的。
*
* bean定义信息包括有哪些呢?有这些,这个bean是单例的还是多例的、bean的类型是什么以及bean的id是什么。
* 也就是说,这些信息都是存在BeanDefinitionRegistry里面的。
*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
// TODO Auto-generated method stub
System.out.println("postProcessBeanDefinitionRegistry...bean的数量:" + registry.getBeanDefinitionCount());
// 除了查看bean的数量之外,我们还可以给容器里面注册一些bean,我们以前也简单地用过
/*
* 第一个参数:我们将要给容器中注册的bean的名字
* 第二个参数:BeanDefinition对象
*/
// RootBeanDefinition beanDefinition = new RootBeanDefinition(Blue.class); // 现在我准备给容器中添加一个Blue对象
// 咱们也可以用另外一种办法,即使用BeanDefinitionBuilder这个构建器生成一个BeanDefinition对象,很显然,这两种方法的效果都是一样的
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Blue.class).getBeanDefinition();
registry.registerBeanDefinition("hello", beanDefinition);
}
}
接下来,我们就来测试一下以上类里面的两个方法是什么时候执行的。运行IOCTest_Ext测试类,我们可以得出这样两个结论
- BeanDefinitionRegistryPostProcessor接口是优先于BeanFactoryPostProcessor接口执行的
- 在BeanDefinitionRegistryPostProcessor接口中,postProcessBeanDefinitionRegistry方法优先于postProcessBeanFactory方法调用 ```shell postProcessBeanDefinitionRegistry…bean的数量: 10 MyBeanDefinitionRegistryPostProcessor…bean的数量:11
MyBeanFactoryPostProcessor…postProcessBeanFactory…
当前BeanFactory中有9个Bean
[org.springframework.context.annotation.internalConfigurationAnnotationProcessor,…,
…,org.springframework.context.event.internalEventListenerFactory,extConfig,myBeanFactoryPostProcessor,blue}
blue…constructor
``
可以看到,首先
postProcessBeanDefinitionRegistry方法先执行,拿到IOC容器中Bean的数量(即10)之后向IOC容器中注册一个hello组件。<br />接着是
postProcessBeanFactory`方法再执行,该方法只是打印了一下IOC容器中Bean的数量11(算上hello)
除此之外,我们自己写的MyBeanDefinitionRegistryPostProcessor类里面的方法都执行完了以后,才轮到外面那些BeanFactoryPostProcessor来执行