这个东西是干嘛的
可以用于自定义对BeanDefinition(而不是具体的bean)的修改,比如:PropertySourcesPlaceholderConfigurer就是用于解决类似@Value(“${…}”)这种占位符的
其实还可以添加BeanDefinition,大家可以思考一下spring啥时候需要添加BeanDefinition…
BeanFactoryPostProcessor接口
@FunctionalInterface
public interface BeanFactoryPostProcessor {
/**
* 在ApplicationContext实例化后修改其内部的BeanFactory.
* 所有的BeanDefinition都已经加载了,但是bean都还没有实例化
* 可以在这里修改BeanDefinition的各种属性(spring源码注释的翻译)
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
它还有一个比较重要的子接口:BeanDefinitionRegistryPostProcessor:
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
大家应该思考了一会上面那个问题,现在揭晓答案(可能只是答案之一):在有@Configuration注解的时候,因为一般情况下我们用基于注解的方式去注册bean,都是一一对应的,比如你在一个类上加@Component,只会生成一个BeanDefinition。只有较新的JavaConfig的这一套@Configuration/@Bean会通过一个类产生出多个BeanDefinition。
Spring中用户处理@Configuration的是ConfigurationClassPostProcessor,它就是BeanDefinitionRegistryPostProcessor的实现类
Spring中对BeanFactoryPostProcessor的调用
先说一下大致的处理流程:
总体上来说是先调用实现BeanDefinitionRegistryPostProcessor的,再调用实现BeanFactoryPostProcessor的;
每一类自己的调用顺序是按照: 手动注册进去的(.addBeanFactoryPostProcessor()方法) -> 实现了PriorityOrdered接口的 -> 实现Ordered接口的 -> 剩下的
就在ApplicationContext的refresh方法中:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
prepareRefresh();
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
try {
postProcessBeanFactory(beanFactory);
//从方法名应该也能看出来,就是它了
invokeBeanFactoryPostProcessors(beanFactory);
registerBeanPostProcessors(beanFactory);
initMessageSource();
initApplicationEventMulticaster();
onRefresh();
registerListeners();
finishBeanFactoryInitialization(beanFactory);
finishRefresh();
} catch (BeansException ex) {
destroyBeans();
cancelRefresh(ex);
throw ex;
} finally {
resetCommonCaches();
}
}
}
点进去能看到,其实真正的处理是:
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
继续进入:
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
//用于避免BeanDefinitionRegistryPostProcessor被处理两遍
Set<String> processedBeans = new HashSet<>();
if (beanFactory instanceof BeanDefinitionRegistry) {//判断BeanFactory的类型,如果没有实现BeanDefinitionRegistry,就没必要走BeanDefinitionRegistryPostProcessor了
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
//手动注册进来的BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<>();
//手动注册进来的BeanDefinitionRegistryPostProcessor
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<>();
//处理手动注册进来的BeanFactoryPostProcessor
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
//这里这是调用呢BeanDefinitionRegistryPostProcessor里的方法,并没有调用BeanFactoryPostProcessor里的方法
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
//首先调用实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
//这几句都是重复的 排序 -> 调用 -> 从当前处理list中清除(后面会直接省略掉...)
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// 调用实现了Ordered接口的
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
//同上的四步
// 调用剩下的
// 可能大家会有问题,为啥上面都是一层循环,这里却是两层
// 答案就是BeanDefinitionRegistryPostProcessor是可以自己再创建一个BeanDefinitionRegistryPostProcessor的BeanDefinition然后放到BeanFactory中去的
// 所以就加了一层循环,用于确保后来生成的那些BeanDefinitionRegistryPostProcessor也可以起作用
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;
}
}
//同上的四步
}
//上面回调的是BeanDefinitionRegistryPostProcessor的方法,这里调的是BeanFactoryPostProcessor的方法
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
} else {
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
//BeanFactoryPostProcessor像之前一样的流程再走一遍
//请注意这里只有实现priorityOrdered才是直接获取到具体事例,其它两种都是这保留了一个name
//原因也是在于,BeanFactory.getBean()被调用时,就意味着bean被真的实例化出来了
//更高优先级的BeanFactoryPostProcessor可能会对后面的BeanFactoryPostProcessor的BeanDefinition有影响
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
//跳过已经在BeanDefinitionRegistryPostProcessor中处理过的
} 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);
}
}
//跟BeanDefinitionRegistryPost类似的过程,分别调用各个postProcessor
//清除一下元数据的缓存,因为这些postProcessor可能已经修改了这些值
beanFactory.clearMetadataCache();
}
注意点
BeanFactoryPostProcessor的调用具体是在AC的refresh()方法中,所以如果是自己想要定义一个BeanFactoryPostProcessor并添加到AC中,那要在refresh()这个方法被调用之前,否则是不会有效的。
还有refresh()方法,是很可能会被间接调用的,比如对于AnnotationConfigApplicationContext,只要实例化的时候加了参数,那么refresh就会被调用
结语
spring5的源码才看一点,PropertySourcesPlaceholderConfigurer/ConfigurationClassPostProcessor的分析放到后面吧…
(水平有限,最近在看spring源码,分享学习过程,希望对各位有点微小的帮助。
如有错误,请指正~)