在此系列文章中,我总结了Spring几乎所有的扩展接口,以及各个扩展点的使用场景。并整理出一个bean在spring中从被加载到最终初始化的所有可扩展点的顺序调用图。这样,我们也可以看到bean是如何一步步加载到spring容器中的。

BeanDefinitionRegistryPostProcessor
1、概述
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor { void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry var1) throws BeansException; }
BeanDefinitionRegistryPostProcessor为容器级后置处理器。容器级的后置处理器会在Spring容器初始化后、刷新前执行一次。还有一类为Bean级后置处理器,在每一个Bean实例化前后都会执行。
通常,BeanDefinitionRegistryPostProcessor用于在bean解析后实例化之前通过BeanDefinitionRegistry对BeanDefintion进行增删改查。
常见如mybatis的Mapper接口注入就是实现的此接口。
2、简单案例
下面是一个示例,展示了如何实现动态的给spring容器添加一个Bean:
public class User { String name; String password; } import org.springframework.beans.BeansException; import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.PropertyValue; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.core.Ordered; import org.springframework.stereotype.Component; @Component public class DynamicBeanRegistration implements BeanDefinitionRegistryPostProcessor, Ordered { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanRegistry) throws BeansException { RootBeanDefinition beanDefinition = new RootBeanDefinition(); beanDefinition.setBeanClass(User.class); MutablePropertyValues propertyValues = new MutablePropertyValues(); PropertyValue propertyValue1 = new PropertyValue("name", "张三"); PropertyValue propertyValue2 = new PropertyValue("password", "123456"); propertyValues.addPropertyValue(propertyValue1); propertyValues.addPropertyValue(propertyValue2); beanDefinition.setPropertyValues(propertyValues); beanRegistry.registerBeanDefinition("user", beanDefinition); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { BeanDefinition beanDefinition = beanFactory.getBeanDefinition("user"); System.out.println(beanDefinition.getBeanClassName()); User user = beanFactory.getBean(User.class); System.out.println(user.getName()); System.out.println(user.getPassword()); } @Override public int getOrder() { return 0; } }
输出:
com.sandy.springex.beanfefinitionregistrypostprocessor.User 张三 123456
- 首先定义了一个名为"User"的Java类,包含了两个属性:name和password。
- 然后定义了一个名为"DynamicBeanRegistration"的组件(通过@Component注解),实现了BeanDefinitionRegistryPostProcessor接口和Ordered接口。
- 在postProcessBeanDefinitionRegistry方法中,创建了一个RootBeanDefinition对象,并设置其beanClass为User类。接着创建了一个MutablePropertyValues对象,并通过PropertyValue对象设置了name和password属性的值。最后,将propertyValues设置到beanDefinition中,并使用beanRegistry注册了一个名为"user"的BeanDefinition。
- 在postProcessBeanFactory方法中,通过beanFactory获取了名为"user"的BeanDefinition,并输出了其beanClassName。然后使用beanFactory获取了一个User对象,并输出了其name和password属性的值。
该代码通过实现BeanDefinitionRegistryPostProcessor接口,在Spring容器启动时动态注册了一个名为"user"的Bean,并设置了其name和password属性的值。在后续的BeanFactory初始化过程中,可以通过beanFactory获取到该动态注册的Bean,并访问其属性值。
当容器中有多个BeanDefinitionRegistryPostProcessor的时候,可以通过实现Ordered接口来指定顺序:
@Override public int getOrder() { return 0; //值越小,优先级越高 }
3、源码分析
- 在DynamicBeanRegistration打上断点,启动SpringApplication,可以看到左下角的调用链路。

- 红框中5步都是在springboot中进行,最后super.refresh()是调用大家熟悉的spring的AbstractApplicationContext的refresh方法。

- 继续向下看


- 接下来进入核心的invokeBeanFactoryPostProcessors方法,大概逻辑是先取出所有实现了BeanDefinitionRegistryPostProcessor接口的类,然后优先调用实现了PriorityOrdered接口的组件,再调用实现了Ordered接口的组件。

- 最后,遍历调用BeanDefinitionRegistryPostProcessor组件postProcessBeanDefinitionRegistry方法
