概述
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`注解3. 验证注入的bean<br /><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
