BeanPostProcessor这个概念可以认为是在spring声明周期中留下的一个钩子,这个钩子是在所有的BeanDefinition被扫描完成之后这个阶段的。我们可以在这里做很多事情,Spring框架里面很多特性也利用了这里,比如属性注入
具体在 查看详细信息
BeanFactoryPostProcessor的定义
在Spring框架设计之中,我们可以看到优秀的设计之处,最为精妙的就是扩展点的设置,这样使我们对Spring的扩展,很多时候只需要继承一个类,把它注册为一个Bean即可。
BeanFactoryPostProcessor从字面的意思上是BeanFactory的后置处理器。也可以认为是在spring生命周期中留下的一个钩子,这个钩子是在所有的BeanDefinition被扫描完成之后这个阶段的。但是在Spring中是这样描述这个扩展点的作用的,
Allows for custom modification of an application context’s bean definitions,
adapting the bean property values of the context’s underlying bean factory`
翻译过来大致是下面个意思
这个扩展点允许修改应用程序上下文(ApplicationContext)中的BeanDefinition,以及bean的属性值。
BeanFactoryPostProcessor 的执行优先级
因为BeanFactoryPostProcessor是一个扩展点,所以当有多个Bean实现这个扩展点的时候,必回存在一个执行顺序的问题,那么Spring是如何设计的呢?
1.执行BeanDefinitionRegistryPostProcessor接口的后置处理器
-
执行通过配置的BeanDefinitionRegistry后置处理器,执行顺序是PriorityOrdered(排序是按照从小到大排)-> Ordered -> 普通的
-
执行硬编码的BeanDefinitionRegistryPostProcessor
2.执行普通的BeanFactoryPostProcessor
-
执行硬编码的后置处理器
-
执行通过配置注册的处理器,执行顺序是PriorityOrdered(排序是按照从小到大排)->Ordered->普通的
在这一节可以看到后置处理器的执行顺序,应该大家都有一个疑惑,这么优秀的东西是如何实现的呢?
不仅大胆的想想,无非就是会把所有的实现这个扩展点的Bean都找出来,然后排序,最后执行,那么Spring是不是这样做的呢?
BeanFactoryPostProcessor的源码阅读
接口定义
在Spring框架中的接口定义如下
public interface BeanFactoryPostProcessor {
// 上下文中的BeanFactory
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
执行逻辑
Spring容器的启动入口
AbstractApplicationContext#refresh
的第三步invokeBeanFactoryPostProcessors
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
prepareRefresh();
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
try {
postProcessBeanFactory(beanFactory);
// 执行上下文中注册的Bean工厂后置处理器
invokeBeanFactoryPostProcessors(beanFactory);
...
}
}
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
//
// 1. 首先执行 BeanDefinitionRegistryPostProcessors (优秀的BeanFactoryPostProcessor)
//
Set<String> processedBeans = new HashSet<String>();
// 1.0 如果beanFactory是BeanDefinitionRegistry类型的,也就是说BeanFactory中允许对BeanDefinition进行增删改的操作
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
// 1.1 先执行硬编码的BeanDefinitionRegistryPostProcessor
List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
List<BeanDefinitionRegistryPostProcessor> registryPostProcessors =
new LinkedList<BeanDefinitionRegistryPostProcessor>();
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryPostProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryPostProcessor.postProcessBeanDefinitionRegistry(registry);
registryPostProcessors.add(registryPostProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
// 1.2 首先执行实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessor
List<BeanDefinitionRegistryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
registryPostProcessors.addAll(priorityOrderedPostProcessors);
invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);
// 1.3 接下来执行实现Ordered接口的BeanDefinitionRegistryPostProcessors
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
List<BeanDefinitionRegistryPostProcessor> orderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
// 排序
sortPostProcessors(beanFactory, orderedPostProcessors);
registryPostProcessors.addAll(orderedPostProcessors);
invokeBeanDefinitionRegistryPostProcessors(orderedPostProcessors, registry);
// 1.4 执行其它的硬编码的的BeanDefinitionRegistryPostProcessors
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
BeanDefinitionRegistryPostProcessor pp = beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class);
registryPostProcessors.add(pp);
processedBeans.add(ppName);
pp.postProcessBeanDefinitionRegistry(registry);
reiterate = true;
}
}
}
// 执行
invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
//
// 2. 执行 BeanFactoryPostProcessor
//
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// 2.1 将后置处理器根据不同类型(PriorityOrdered、Ordered、其它)分组
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
List<String> orderedPostProcessorNames = new ArrayList<String>();
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// 2.2 首先执行优先级Order类型的后置处理器
sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 2.3 执行带有Order接口的后置处理器
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(beanFactory, orderedPostProcessors);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// 2.4 执行其它的所有后置处理器
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// 清空元数据cache,因为beandefine有可能会变
beanFactory.clearMetadataCache();
}
BeanFactoryPostProcessor 在Spring中的应用
在Spring中,有很多的框架类实现了这个类并且做了一些事情。。
上图是一个只依赖spring-boot-starter-web的空工程中所有的BeanFactoryPostProcessor实现,可以看到有以下扩展点
- PropertyResourceConfigurer。配合上PlaceholderResolvingStringValueResolver,为@Value注解提供支持
- BeanDefinitionRegistryPostProcessor,这个比如Dubbo中的Reference和Service就是通过这个接口在Spring容器中注册为Bean 的,比较适用于一些框架添加自定义的Bean的场景。
- CustomScopeConfigurer(自定义的Scope处理)
- ServletComponentRegisteringPostProcessor(自动扫描Servlet的三剑客)
- DeprecatedBeanWarner(在Bean上面添加一个过期的标志,有意思)
- AbstractDependsOnBeanFactoryPostProcessor(用于动态声明特定类型的所有bean应该依赖于一个或多个特定bean。,应用场景比如在一些框架上,有一些Bean进行初始化之前必须等待一些连接类Bean准备好,如这里面的MongoClient,MongoClientFactoryBean)
- CustomAutowireConfigurer,自定义Qualifier类型,和
@Qualifier
一个意思 - ConfigurationBeanFactoryMetaData 在bean工厂初始化期间记住Bean定义元数据的一个工具类。保存了工厂方法名称和工厂Bean的名称,可以后续根据beanName
BeanFactoryPostProcessor 小例子
- 使用BeanFactoryPostProcessor注册一个bean
@Component
public class RegisteBeanBeanDefinitionRegistry implements BeanDefinitionRegistryPostProcessor,Ordered {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
RootBeanDefinition rbd = new RootBeanDefinition();
rbd.setTargetType(User.class);
rbd.setBeanClass(User.class);
registry.registerBeanDefinition("user-wuhulala", rbd);
}
@Override
public int getOrder() {
return 0;
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// do nothing
}
}
- 使用BeanFactoryPostProcessor丰富Bean的属性
public class ModifyBeanBeanFactoryPostProcessor implements BeanFactoryPostProcessor,Ordered {
@Override
public int getOrder() {
return 0;
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
RootBeanDefinition bd = (RootBeanDefinition) beanFactory.getBeanDefinition("user-wuhulala");
MutablePropertyValues values = new MutablePropertyValues();
values.addPropertyValue("name", "wuhulala");
values.addPropertyValue("age", 21);
Address address = new Address();
address.setName("浙江省");
values.addPropertyValue("address", address);
bd.setPropertyValues(values);
}
}
使用BeanFactoryPostProcessor注意点
- 如果使用BeanDefinitionRegistry接口,那么应该是对当前IOC容器的Bean的一种补充或删除。
- BeanFactoryPostProcessor可以操作BeanDefinition,但永远不要与bean实例交互。也就是不要在这里进行Bean的实例化。 因为在这里实例化的话会过早,违反了容器的设计规则并有可能会导致意外的副作用。比如这里初始化的Bean依赖于其它的Bean,就会导致这个链路上的Bean都进行了初始化,从而导致它依赖Bean没有被BeanFactoryPostProcessor处理过对应的BeanDefinition。如果需要bean实例交互,可以实现另一个扩展点 BeanPostProcessor。
- 在BeanFactoryPostProcessor不要进行Bean的注册。
聊聊设计
Spring扩展点在Spring核心中是很重要的概念,spring本身就内置了很多实现。如果我们需要扩展Spring的功能,他们是很好的方式。并且它们可以像插件一样很好的工作。
在我们日常进行程序的设计编码时候,当一处进行多次的修改(添加、删除、修改细节)的时候,我们也可以尝试着抽取出一个扩展点,这样会使我们的程序变得极为简单。
比如我最近在做的一个项目流程,其实在项目新增之前和之后都需要进行很多的逻辑处理,比如调用远程服务、参数校验、后置处理,并且需求变动很频繁,那么现在依葫芦画瓢,把项目流程分为新增前、新增、新增后三个逻辑,抽象出preAddProcessor/postAddProcessor两个接口,最后用一段通用逻辑进行拼接,如有兴趣,可私聊。