一、介绍
BeanPostProcessor接口定义了回调方法,开发者可以实现这些回调方法来提供自定义的实例化逻辑、依赖项解析逻辑等等。BeanPostProcessor也叫Bean后处理器,Spring框架会加载Bean过程中特定的步骤,来调用Bean后处理器中的接口方法,并传入一些值给这些回调方法。具体可参考:spring中常用的BeanPostProcessor、Spring官方文档介绍
二、BeanPostProcessor存在哪儿?
本篇文章重点不在于哪些地方回调了这些方法,而是要介绍这些BeanPostProcessor何时注册到容器中的。我们首先看下BeanPostProcessor存在容器的哪个地方,从回调接口方法的地方找起。回调方法有很多处,我们挑一处初始化bean前的回调源码:
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
// 1. 调用Aware方法
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 2. 回调Bean后处理器的postProcessBeforeInitialization
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 3. 调用bean的初始化方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 4. 回调Bean后处理器的postProcessAfterInitialization方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
该代码片段来自于AbstractAutowireCapableBeanFactory类的initializeBean方法,可以看到第2步和第4步都调用了BeanPostProcessor的接口方法,我们点进去看看第2个步骤中的代码
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
// 循环容器中所有的BeanPostProcessor
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
// 调用BeanPostProcessor的postProcessBeforeInitialization方法
Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
调用BeanPostProcessor的哪个方法我们不关心,我们只关心容器中的BeanPostProcessor从哪儿来的,继续看下getBeanPostProcessors()这个方法:
/** BeanPostProcessors to apply in createBean */
private final List<BeanPostProcessor> beanPostProcessors = new ArrayList<>();
public List<BeanPostProcessor> getBeanPostProcessors() {
return this.beanPostProcessors;
}
这段代码在AbstractBeanFactory类中,所以容器中所有的BeanPostProcessor都存在AbstractBeanFactory类中的beanPostProcessors属性里。
三、注册BeanPostProcessor源码
从上面我们看到了,容器中的BeanPostProcessor都存在AbstractBeanFactory类中的beanPostProcessors属性中。那么是何时注册进去的呢?顺序有是怎样的呢?
1. 初始化容器的代码
来看下ApplicationContext初始化(也叫刷新Application上下文)的经典代码:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 1. 准备刷新的上下文环境
prepareRefresh();
// 2. 初始化BeanFactory,并进行XML文件的加载
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 3. 对BeanFactory进行各种功能填充
prepareBeanFactory(beanFactory);
try {
// 4. 子类覆盖犯法做额外的处理
postProcessBeanFactory(beanFactory);
// 5. 调用BeanFactory后处理器
invokeBeanFactoryPostProcessors(beanFactory);
// 6. 注册bean后处理器,在调用getBean的时候回调这些bean后处理器的方法
registerBeanPostProcessors(beanFactory);
// 7. 为上下文初始化Message源
initMessageSource();
// 8. 初始化应用消息广播器,并放入ApplicationEventMulticaster中
initApplicationEventMulticaster();
// 9. 留给子类初始化其他bean
onRefresh();
// 10. 注册监听器
registerListeners();
// 11. 初始化剩下的单例Bean(非惰性的)
finishBeanFactoryInitialization(beanFactory);
// 12. 最后一步,发布通知事件
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// 销毁已经创建的单例,以避免挂起资源。
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
该代码来自AbstractApplicationContext类的refresh方法,是ApplicationContext初始化的入口。整个Spring框架加载的过程就是这个方法中,可以好好看一下。
很显然跟BeanPostProcessor注册相关的就是第6步,点进去看下
2. 注册BeanPostProcessor
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
转发到了PostProcessorRegistrationDelegate类的registerBeanPostProcessors方法,点进去看下:
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
// 获取所有BeanPostProcessor类型的beanName
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// 1. 注册一个BeanPostProcessorChecker
// 当一个bean在BeanPostProcessor实例化过程中被创建时,
// 也就是当一个bean没有资格被所有BeanPostProcessor处理时,它会输出一条日志。
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// 2. 给BeanPostProcessor分类:实现了PriorityOrdered、Ordered接口和其他普通BeanPostProcessor
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
// 2.1 初始化实现PriorityOrdered接口的BeanPostProcessor
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
// 2.1.1 如果是MergedBeanDefinitionPostProcessor类型,记录到internalPostProcessors
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
// 2.2 记录实现Ordered接口的Bean后处理器名称
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
// 2.3 记录其他Bean后处理器名称
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// 3. 注册BeanPostProcessor
// 3.1 注册实现PriorityOrdered接口的BeanPostProcessors
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// 3.2 注册实现Ordered接口的BeanPostProcessors
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
for (String ppName : orderedPostProcessorNames) {
// 根据beanName从容器中获取bean
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// 3.3 注册剩下的BeanPostProcessors
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// 4. 注册MergedBeanDefinitionPostProcessor类型的Bean后处理器
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// 5. 最后在注册一个ApplicationListenerDetector类型的Bean后处理器
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
从上面代码我们可以看到,此逻辑注册了6种BeanPostProcessor,它们的顺序如下:
- BeanPostProcessorChecker
作用:当某些非BeanPostProcessor的Bean实例,在BeanPostProcessor实例化过程中被创建时输出一条日志。 - 实现PriorityOrdered接口的BeanPostProcessor
- 实现Ordered接口的BeanPostProcessor
- 其他BeanPostProcessor
- 实现PriorityOrdered接口且类型为MergedBeanDefinitionPostProcessorBean
这个都可以当面试题了,是否所有实现了PriorityOrdered接口的BeanPostProcessor的优先级,都比实现Ordered接口的BeanPostProcessor优先级高? - ApplicationListenerDetector
作用:记录容器中监听器的beanName
读者看完以上代码可能会存在以下两个问题:
- BeanPostProcessor是否重复注册了?
代码如下:
// 2.1 初始化实现PriorityOrdered接口的BeanPostProcessor
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
// 2.1.1 如果是MergedBeanDefinitionPostProcessor类型,记录到internalPostProcessors
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
// 省略其他无关代码...
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
有些BeanPostProcessor添加到priorityOrderedPostProcessors和internalPostProcessors中,是否重复注册了呢?继续看下注册代码就明白了:
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
// 先移除
this.beanPostProcessors.remove(beanPostProcessor);
// 再添加
this.beanPostProcessors.add(beanPostProcessor);
if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
this.hasInstantiationAwareBeanPostProcessors = true;
}
if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
this.hasDestructionAwareBeanPostProcessors = true;
}
}
注册之前,会把原来的BeanPostProcessor给移除掉,所以不会重复注册。
- 为什么初始化实现PriorityOrdered接口的BeanPostProcessor时,不初始化其他BeanPostProcessor?
在获取实现PriorityOrdered接口的BeanPostProcessor时,是使用beanFactory.getBean(ppName, BeanPostProcessor.class)直接初始化Bean的;而获取其他的BeanPostProcessor时,是使用orderedPostProcessorNames.add(ppName),仅保存了BeanPostProcessor的bean名称,放到后面初始化的。为什么不一起使用beanFactory的getBean方法加载bean呢?应该是因为注册完优先级高的BeanPostProcessor后,再加载优先级低的BeanPostProcessor,此时已注册完的BeanPostProcessor就能起作用了。
四、 其他注册位置
BeanPostProcessor最主要的注册逻辑,在上面讲解的AbstractApplicationContext类的registerBeanPostProcessors方法中。但是这个方法不是唯一的注册逻辑,除此之外还有其他Spring内部硬编码注册的地方。
所谓的注册就是把创建的BeanPostProcessor保存在AbstractBeanFactory类中的beanPostProcessors属性中。
1. 刷新Application上下文
在上面刷新Application上下文代码中的第3步,AbstractApplicationContext类的prepareBeanFactory方法中也有注册BeanPostProcessor的一些代码,注册的都是Spring内置的Bean后处理器。
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// 1. 注册Bean后处理器:ApplicationContextAwareProcessor
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
// 省略无关代码...
// 2. 注册Bean后处理器:ApplicationListenerDetector
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
// 3. 注册Bean后处理器:LoadTimeWeaverAwareProcessor
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// 省略无关代码...
}
有三处注册了Bean后处理器
2. ConfigurationClassPostProcessor
ConfigurationClassPostProcessor是一个BeanFactory后处理器,在注册BeanPostProcessor的主逻辑前,会调用BeanFactory后处理器的postProcessBeanFactory方法,那么我们来看下ConfigurationClassPostProcessor类的postProcessBeanFactory方法代码:
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
int factoryId = System.identityHashCode(beanFactory);
if (this.factoriesPostProcessed.contains(factoryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + beanFactory);
}
this.factoriesPostProcessed.add(factoryId);
if (!this.registriesPostProcessed.contains(factoryId)) {
// BeanDefinitionRegistryPostProcessor hook apparently not supported...
// Simply call processConfigurationClasses lazily at this point then.
processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
}
enhanceConfigurationClasses(beanFactory);
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}
五、借鉴Spring内部用法
- 根据类型获取容器中的bean名称
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
- 判断beanName对应的类型是否匹配
// ppName的bean是否是PriorityOrdered类型
boolean match = beanFactory.isTypeMatch(ppName, PriorityOrdered.class);
- 根据beanName和类型从容器中获取bean实例
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);