「这是我参与11月更文挑战的第9天,活动详情查看:2021最后一次更文挑战」
1.前言
本文是Spring IOC容器初始化原理分析系列第三节,紧接上篇Spring IOC容器初始化原理分析 (第二节),其中本篇文章主要分析refresh() 中的 registerBeanPostProcessors(beanFactory)方法。
2.refresh() 源码
废话不多说,还是老规矩,先贴图,如果需要复制代码,可前往Spring IOC容器初始化原理分析 (第一节)
3.registerBeanPostProcessors(beanFactory)理解
这个方法必须要在bean实例化前调用,按照特定的顺序,实例化并注册所有BeanPostProcessor bean,将所有实现了 BeanPostProcessor 接口的类加载到 BeanFactory 中。
在讲这个方法前,先来讲一下 BeanPostProcessor,Bean后置处理器。Spring IoC 容器允许 BeanPostProcessor 在容器初始化 bean 的前后,添加自己的逻辑处理,它是Spring中定义的接口,在Spring容器的创建过程中会回调BeanPostProcessor中定义的两个方法。在本方法中只是注册BeanPostProcessor,具体调用是在Bean初始化前后
- BeanPostProcessor 它是一个接口,其中包含了两个方法,postProcessBeforeInitialization 这个方法主要是在 bean初始化前调用 ,postProcessAfterInitialization 这个方法 主要是在bean初始化后调用
接下来 我们继续看 registerBeanPostProcessors(BeanFactory)方法
里面就一行代码,接着点进去
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
//首先拿到所有的实现了BeanPostProcessor接口的类名
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// Register BeanPostProcessorChecker that logs an info message when
// a bean is created during BeanPostProcessor instantiation, i.e. when
// a bean is not eligible for getting processed by all BeanPostProcessors.
//注册BeanPostProcessorChecker,当bean在BeanPostProcessor实例化期间创建时,
//即当bean不符合所有BeanPostProcessors处理的条件时,该checker会记录信息消息。
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
//把刚刚注册的BeanPostProcessorChecker添加到beanFactory中去
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
// 定义不同的集合 用于记录实现了不同排序接口的 BeanPostProcessors
//记录实现了PriorityOrdered接口的 BeanPostProcessors
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
// 记录实现了MergedBeanDefinitionPostProcessor接口的 BeanPostProcessors
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
// 记录实现了 Ordered接口的 BeanPostProcessors的beanName
List<String> orderedPostProcessorNames = new ArrayList<>();
// 记录实现了 没有实现排序接口的 BeanPostProcessors的beanName
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
// 遍历postProcessorNames,按照类型加入到对应的list集合中
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, register the BeanPostProcessors that implement PriorityOrdered.
// 首先 对记录了 实现PriorityOrdered接口的BeanPostProcessors集合 进行排序
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 点进去这个方法他们把每一个BeanPostProcessors 注册到容器中去
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// Next, register the BeanPostProcessors that implement Ordered.
// 其次,通过orderedPostProcessorNames集合记录的beanName 找到对应的 BeanPostProcessors
// 同时判断是否有实现了MergedBeanDefinitionPostProcessor接口的,如果有就把它加入到
//internalPostProcessors集合中去,然后把所有实现了Ordered接口的 BeanPostProcessors 先排序后注册到容器中去
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// Now, register all regular BeanPostProcessors.
// 这里的操作和上面对于实现Ordered接口的 BeanPostProcessors操作一样,写在这里,只是为了保证执行顺序
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// Finally, re-register all internal BeanPostProcessors.
// 最后注册所有实现了 MergedBeanDefinitionPostProcessor 接口的 BeanPostProcessors
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// Re-register post-processor for detecting inner beans as ApplicationListeners,
// moving it to the end of the processor chain (for picking up proxies etc).
// 重新注册后置处理器 用于检测内部bean作为ApplicationListeners,将其移动到处理器链的末尾
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
4.重点总结
这个方法主要作用就是在bean实例化之前,实例化并注册所有 BeanPostProcessor。 其中有几个特殊的BeanPostProcessor,我们挑出来讲一讲
4.1 BeanPostProcessorChecker
这个后置处理器的主要作用是:记录创建bean时,所有的BeanPostProcessor都不能处理的bean,这个类的实例对象用于这个不能被处理的bean的信息,把这些信息以日志的形式打印出来。 源代码贴在下面 大家有兴趣的可以自己看看 org.springframework.context.support.PostProcessorRegistrationDelegate.BeanPostProcessorChecker
4.2 MergedBeanDefinitionPostProcessor
我们发现在public static void registerBeanPostProcessors( ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext)方法中,会把所有实现了MergedBeanDefinitionPostProcessor接口的类 单独抽出来放在一个集合中
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {
//对指定的bean 合并属性信息,这里主要是子类(扫描注解里的信息,合并到bean中)
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
//通知指定名称的bean定义已被重置,并且此后处理器应清除受影响bean的任何元数据。
default void resetBeanDefinition(String beanName) {
}
}
贴出一下它的子类 有兴趣大家可以继续关注
4.3 ApplicationListenerDetector
-
ApplicationListenerDetector 主要作用就是处理 处理用户自定义的ApplicationListener的注册和销毁
-
在Bean初始化完成之后:如果Bean是单例的则并且bean instanceof ApplicationListener。则把它注册到this.applicationListeners中。
-
在ApplicationListener销毁之前,则会从ApplicationEventMulticaster(事件广播器)中提前删除了。
4.4 小结
后续源码将接着在本专栏 继续分析,如有兴趣,可订阅本专栏