概述
Spring中的每个bean的创建是依赖一个对应的`BeanDefintion`实例,该实例保存了bean对象创建必要的信息,比如bean的class类型,是否是抽象类、属性信息等。`BeanDefinitionRegistry`是一个接口,bean定义信息的注册中心,用于注册、删除、管理`BeanDefintion`。<br /> 如果外部想要添加Bean的定义信息,创建新的Bean, 怎么办? 当然是可以通过Spring提供的扩展接口`BeanDefinitionRegistryPostProcessor`实现,比较典型的一个案例是mybatis-spring,就是通过实现该接口,添加mybatis相关的bean。<br /> 所以,`**BeanDefinitionRegistryPostProcessor**`**就是bean定义注册中心的后置处理器,允许我们修改拓展bean定义信息的注册中心,在所有bean定义信息将要被加载,bean实例还未创建的时候执行。**
使用实例
新建类实现
BeanDefinitionRegistryPostProcessor
```java @Component public class TestBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {log.info("******************** TestBeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry ****************");
log.info("******************** bean的数量:[{}] ****************", beanDefinitionRegistry.getBeanDefinitionCount());
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();
MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
propertyValues.addPropertyValue("username", "alvin");
propertyValues.addPropertyValue("age", 12);
// 注册bean信息
beanDefinitionRegistry.registerBeanDefinition("beanDefineDemo", beanDefinition);
}
@Override public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
log.info("******************** TestBeanDefinitionRegistryPostProcessor#postProcessBeanFactory ****************");
log.info("******************** bean的数量:[{}] ****************", configurableListableBeanFactory.getBeanDefinitionCount());
} }
2. 实现类需要添加`@Component`注解
![image.png](https://cdn.nlark.com/yuque/0/2022/png/384158/1654061737063-3893a070-bcfc-4946-a896-842188179314.png#clientId=ud7accf57-2ef8-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=175&id=u9e84b8fe&margin=%5Bobject%20Object%5D&name=image.png&originHeight=175&originWidth=647&originalType=binary&ratio=1&rotation=0&showTitle=false&size=21448&status=done&style=none&taskId=ue923855d-f826-4be0-b046-8f25c8b03c1&title=&width=647)
3. 验证注入的bean
![image.png](https://cdn.nlark.com/yuque/0/2022/png/384158/1654061762922-d7d668a9-56ef-4c0e-9ca5-d0a7c9cb08f8.png#clientId=ud7accf57-2ef8-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=242&id=ue393d30b&margin=%5Bobject%20Object%5D&name=image.png&originHeight=242&originWidth=921&originalType=binary&ratio=1&rotation=0&showTitle=false&size=36749&status=done&style=none&taskId=ua5ad40d1-08c0-4110-a364-d381fbf302b&title=&width=921)<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/384158/1654061772381-da50fa51-2890-4f9e-8e65-6485b6446c65.png#clientId=ud7accf57-2ef8-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=47&id=ufcc92ed2&margin=%5Bobject%20Object%5D&name=image.png&originHeight=47&originWidth=1207&originalType=binary&ratio=1&rotation=0&showTitle=false&size=9943&status=done&style=none&taskId=u32a98b6e-e9cd-4e16-8c3a-2f3e6bdeb84&title=&width=1207)
<a name="nqAkU"></a>
# 源码解析
> 可以通过debug的方式,在postProcessBeanDefinitionRegistry方法中打上断点,查看Deubbger中的Frames记录,快速定位代码的调用链路。
<a name="OAsYd"></a>
## 接口的定义说明
```java
/**
* 扩展到标准的{@link BeanFactoryPostProcessor} SPI
* 允许在常规BeanFactoryPostProcessor检测开始之前注册更多的bean定义。
* 特别是,BeanDefinitionRegistryPostProcessor可以注册更多的bean定义,
* 这些定义反过来又定义了BeanFactoryPostProcessor实例。
*
* Extension to the standard {@link BeanFactoryPostProcessor} SPI, allowing for
* the registration of further bean definitions <i>before</i> regular
* BeanFactoryPostProcessor detection kicks in. In particular,
* BeanDefinitionRegistryPostProcessor may register further bean definitions
* which in turn define BeanFactoryPostProcessor instances.
*
* @author Juergen Hoeller
* @since 3.0.1
* @see org.springframework.context.annotation.ConfigurationClassPostProcessor
*/
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
/**
* 在标准初始化之后修改应用程序上下文的内部bean定义注册表。所有常规bean定义都已加载,
* 但还没有实例化bean。这允许在进入下一个后处理阶段之前添加更多的bean定义。
*
* Modify the application context's internal bean definition registry after its
* standard initialization. All regular bean definitions will have been loaded,
* but no beans will have been instantiated yet. This allows for adding further
* bean definitions before the next post-processing phase kicks in.
* @param registry the bean definition registry used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
通过翻译看,此接口目的是为了提供给开发者向容器中注册更多的BeanDefinition, 实现动态注册bean的目的。
执行流程
以上是整个执行的序列图,关键点是AbstractApplicationContext#refresh()
。
1. AbstractApplicationContext#refresh()
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// Prepare this context for refreshing.
// 刷新上下文的准备阶段,跳过
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// 创建beanFacotry工厂
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// beanFactory准备工作, 跳过
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
// 调用注册的BeanFactoryPostProcessors对象
invokeBeanFactoryPostProcessors(beanFactory);
}
}
2. AbstractApplicationContext#invokeBeanFactoryPostProcessors
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// 注册的核心代码, beanFactory代表当前的容器, 第二个参数为内置的参数处理器
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
.....
}
3. PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// WARNING: Although it may appear that the body of this method can be easily
// refactored to avoid the use of multiple loops and multiple lists, the use
// of multiple lists and multiple passes over the names of processors is
// intentional. We must ensure that we honor the contracts for PriorityOrdered
// and Ordered processors. Specifically, we must NOT cause processors to be
// instantiated (via getBean() invocations) or registered in the ApplicationContext
// in the wrong order.
//
// Before submitting a pull request (PR) to change this method, please review the
// list of all declined PRs involving changes to PostProcessorRegistrationDelegate
// to ensure that your proposal does not result in a breaking change:
// https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate+is%3Aclosed+label%3A%22status%3A+declined%22
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
// 如果存在BeanDefinitionRegistryPostProcessors,那么就会首先调用。
Set<String> processedBeans = new HashSet<>();
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
// 常规的BeanFactory后置处理器集合
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
// Bean定义注册的后置处理器
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
// 遍历容器优先内置的后置处理器
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
// 判断是否为Bean定义注册的后置处理器
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
// 直接调用postProcessBeanDefinitionRegistry方法
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
// 定义外部实现了BeanDefinitionRegistryPostProcessor扩展的集合
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
// 首先,调用实现PriorityOrdered的 BeanDefinitionRegistryPostProcessor。
// 此处获取的postProcessorNames必须是已经进行注册过的BeanDefinition。
// 第一次我们无法找到我们写的BeanDefinitionRegistryPostProcessor,是因为它本身并未注册到bean定义注册中心。
// 但是会发现有ConfigurationClassPostProcessor,它会帮我们写的PostProcessor注册到bean定义注册中心。
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 判断BeanDefinitionRegistryPostProcessor是否实现了PriorityOrdered接口
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
// 根据优先级排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 真正执行后置处理器
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
// 再次获取BeanDefinitionRegistryPostProcessor后置处理器,此时可以看到我们写的后置处理器,
// 那是因为我们写的后置处理器bean定义经过ConfigurationClassPostProcessor注册
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 判断是否实现了Ordered接口
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 真正执行后置处理器
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
// 最后执行没有实现Orderd接口的后置处理器
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
}
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
// 因为
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// 后面的内容是执行BeanFactoryPostProcessor的后置处理器,后面再说
.....
}
小结:
- 自己定义的后置处理器想要生效,前提是必须本身要被注册到BeanDefinitionRegistry注册中心,这也是为什么我们需要加
@Component
注解。 - 那我们添加
@Component
注解的后置处理器在上面时候注册到BeanDefinitionRegistry注册中心呢? 实在ConfigurationClassPostProcessor
中动态注册的,这也是为什么第一次获取BeanDefinitionRegistryPostProcessor
相关的bean name时候,没有找到我们写的,因为我们写的还没有注册到BeanDefinitionRegistry注册中心。 BeanDefinitionRegistryPostProcessor
的执行顺序是,实现了@PriorityOrdered
优先执行,其次是实现了@Ordered
,最后是没有实现的后置处理器。内置的BeanDefinitionRegistryPostProcessor
SpringBoot比较重要的内置的BeanDefinitionRegistryPostProcessor
后置处理器是ConfigurationClassPostProcessor
,它主要是帮我们完成注解扫描和类定义注册,然后再由BeanFactory完成实例化以及初始化逻辑,那它本身是在什么时候注册到注册中心的呢,内部原理又是什么样呢?参考
https://juejin.cn/post/6844903874491318280#heading-8
https://blog.csdn.net/qq_42154259/article/details/108315262
https://www.cnblogs.com/warrior4236/p/13157671.html
https://cloud.tencent.com/developer/article/1928593