概述
Spring中的每个bean的创建是依赖一个对应的BeanDefintion
实例,该实例保存了bean对象创建必要的信息,比如bean的class类型,是否是抽象类、属性信息等。BeanDefinitionRegistry
是一个接口,bean定义信息的注册中心,用于注册、删除、管理BeanDefintion
。
如果外部想要添加Bean的定义信息,创建新的Bean, 怎么办? 当然是可以通过Spring提供的扩展接口BeanDefinitionRegistryPostProcessor
实现,比较典型的一个案例是mybatis-spring,就是通过实现该接口,添加mybatis相关的bean。
所以,BeanDefinitionRegistryPostProcessor
就是bean定义注册中心的后置处理器,允许我们修改拓展bean定义信息的注册中心,在所有bean定义信息将要被加载,bean实例还未创建的时候执行。
使用实例
- 新建类实现
BeanDefinitionRegistryPostProcessor
@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()); } }
- 实现类需要添加
@Component
注解
- 验证注入的bean
源码解析
可以通过debug的方式,在postProcessBeanDefinitionRegistry方法中打上断点,查看Deubbger中的Frames记录,快速定位代码的调用链路。
接口的定义说明
/** * 扩展到标准的{@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完成实例化以及初始化逻辑,那它本身是在什么时候注册到注册中心的呢,内部原理又是什么样呢?