首页 技术 正文
技术 2022年11月13日
0 收藏 900 点赞 4,334 浏览 14964 个字

Spring Ioc源码分析系列–Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理

前言

上一篇分析了BeanFactoryPostProcessor的作用,那么这一篇继续在refresh()方法里游荡,相信对Spring熟悉点的朋友,在看完BeanFactoryPostProcessor后,一定会想到Spring里面还有个BeanPostProcessor,那这个东西是什么作用呢?下面会进行介绍,同时由于注册BeanPostProcessor的逻辑比较简单,这里会穿插一下BeanPostProcessor生效的时机和源码逻辑,实际上这部分应该是Bean实例化出现的逻辑。

介绍完这部分之后,会介绍Spring的消息源初始化、广播器的初始以及监听器的初始化。这部分工作完成之后,Spring容器就会进入到Bean的创建过程,因为准备工作已经做得差不多了,容器已经准备好,接下来就是初始化Bean放进去容器里面。

BeanFactoryPostProcessor和BeanPostProcessor之间的区别

这两个的区别还是很显而易见的,主要表现在应用的阶段不同BeanFactoryPostProcessor是对BeanDefinition直接生效的,这更加底层,也更加原始,所以直接使用BeanFactoryPostProcessor会比较少。BeanPostProcessor是对bean实例生效的,相对于对BeanDefinition的处理,这个阶段更加靠后,BeanFactoryPostProcessor阶段bean是尚未初始化出来的,BeanPostProcessor处理的时候已经生成了实例对象,BeanPostProcessor会在对象的实例基础上进行一个更进一步的加工。

不熟悉的朋友看起来可能有点抽象,那么这里举一个例子吧。

BeanFactoryPostProcessor的类比:

假设你要造一个杯子,那么杯子需要一份原材料列表,材质你可以选择铁、铜、金、银等等,样式你可以选择圆型、方形、椭圆等等。假设开始原料选择铁,形状为圆形,那么这一份原料列表对应的就是一个BeanDefinition。原料列表出来后,没什么问题就会按照这一份列表去创建一个杯子。但是有时候需要一些额外的操作,例如对某些BeanDefinition进行检查,假设有一个检查员BeanFactoryPostProcessor去检查每个BeanDefinition。他看到杯子的材质是铁,觉得有失身份,于是把材料改成了金子,于是后续再去创建杯子的时候,就是个金杯了。

BeanPostProcessor的类比:

BeanPostProcessor的处理阶段则要靠后,在上面杯子创建完成之后,才到了BeanPostProcessor出场。BeanPostProcessor会在实例的基础上进行一些加工,拿杯子来举例,上一个阶段拿到的是一个粗糙的杯子,这里会进行一些处理,例如给杯子加点花纹样式,给杯子抛光等等。**注意这些操作都是在一个已有的杯子上进行的,但是请注意,这不是绝对的。**BeanPostProcessor除了能对Bean进行深加工外,还能直接进行Bean替换,类比来说,就是换了个杯子,偷梁换柱。Spring Aop的功能就是这样实现的,把经过代理的Bean放了进去,替换了原有的Bean。

所以比较一下得出一个很明显的结论:

  • BeanFactoryPostProcessor对BeanDefinition生效

  • BeanPostProcessor对bean实例生效

源码分析

registerBeanPostProcessors(beanFactory)

话不多说,下面继续分析refresh()方法里面的子方法,上一篇分析到了第五个子方法,那这篇从第六个registerBeanPostProcessors(beanFactory)开始。

跟进代码,可以看到实现都委托给了PostProcessorRegistrationDelegate#registerBeanPostProcessors(beanFactory, this)方法。

/**
* Instantiate and register all BeanPostProcessor beans,
* respecting explicit order if given.
* <p>Must be called before any instantiation of application beans.
*
* 实例化并注册所有 BeanPostProcessor bean,如果给定顺序,则按照顺序排序。
* <p>必须在应用程序 bean 的任何实例化之前调用。
*/
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

继续跟进,这个方法的逻辑也是比较简单的,跟上篇的BeanFactoryPostProcessor注册类似,这里也会按照优先级去对BeanPostProcessor进行排序然后按顺序进行注册。都是些家常套路了,可以跟着注释去看一下。值得注意的是,这里会额外加入两个BeanPostProcessor,分别为BeanPostProcessorCheckerApplicationListenerDetectorBeanPostProcessorChecker主要是用来记录一些日志,ApplicationListenerDetector是用来检测实现了ApplicationListener但是getBeanNamesForType()没探测出来的漏网之鱼。这里的漏网之鱼可能是一些动态注册的bean或者一些内部类,这里再次获取后会放入到applicationListeners集合里。

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.
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
// 注册 BeanPostProcessorChecker,当 bean 不符合所有 BeanPostProcessor 处理的条件时,它会在 BeanPostProcessor 实例化期间创建 bean 时记录一条信息消息
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
// 按照顺序分类区分 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) {
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 接口的 BeanPostProcessor
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);// Next, register the BeanPostProcessors that implement Ordered.
// 其次注册实现了 Ordered 接口的 BeanPostProcessor
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.
// 现在到了注册没有实现上述接口的 BeanPostProcessor
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.
// 最后,重新注册所有内部 BeanPostProcessor MergedBeanDefinitionPostProcessor。
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));
}

initMessageSource()

接下来继续进行下一步的准备工作,初始化消息源。这里是默认使用了父类的消息源,如果没有就初始化一个DelegatingMessageSource,这个DelegatingMessageSource会默认将所有的调用都委派到父容器的消息源去解析,如果没有父容器的消息源,那么它不会解析任何消息。

/**
* Initialize the MessageSource.
* Use parent's if none defined in this context.
* 初始化消息源。如果没有在此上下文中定义,则使用父容器的。
*/
protected void initMessageSource() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 返回当前容器职工是否存在 messageSource,忽略祖先容器
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
// Make MessageSource aware of parent MessageSource.
// 如果存在祖先,并且 messageSource 类型是 HierarchicalMessageSource,则获取祖先的 messageSource 设置到当前 messageSource 里。
if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
if (hms.getParentMessageSource() == null) {
// Only set parent context as parent MessageSource if no parent MessageSource
// registered already.
hms.setParentMessageSource(getInternalParentMessageSource());
}
}
if (logger.isTraceEnabled()) {
logger.trace("Using MessageSource [" + this.messageSource + "]");
}
}
else {
// Use empty MessageSource to be able to accept getMessage calls.
// 本地不存在 messageSource,使用空 MessageSource 能够接受 getMessage 调用
DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
if (logger.isTraceEnabled()) {
logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
}
}
}

initApplicationEventMulticaster()

初始化 ApplicationEventMulticaster,如果上下文中没有定义,则使用 SimpleApplicationEventMulticaster

/**
* Initialize the ApplicationEventMulticaster.
* Uses SimpleApplicationEventMulticaster if none defined in the context.
*
* 初始化 ApplicationEventMulticaster。
* 如果上下文中没有定义,则使用 SimpleApplicationEventMulticaster。
*
* @see org.springframework.context.event.SimpleApplicationEventMulticaster
*/
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 如果本地容器里存在 applicationEventMulticaster,直接使用本地容器里的 applicationEventMulticaster
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isTraceEnabled()) {
logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
// 否则使用 SimpleApplicationEventMulticaster 广播器
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
// 将给定的单例对象添加到该工厂的单例缓存中
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isTraceEnabled()) {
logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
}
}
}

这个事件广播器是干什么的呢?其实很简单,就是把一个事件广播到所有的ApplicationListener上。可以看一下里面的关键方法SimpleApplicationEventMulticaster#multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType),这里就是获取所有的listener,如果有异步线程池,则异步执行,否则逐个调用。

@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
// 解析事件的类型,这个type会用于后续的 ListenerCacheKey 缓存 key 构建
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
// 获取线程池
Executor executor = getTaskExecutor();
// 逐个广播事件到 listener,就是将 listener 都遍历调用一遍
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
// 错误处理器,记录任务处理期间发生的错误
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
doInvokeListener(listener, event);
}
catch (Throwable err) {
errorHandler.handleError(err);
}
}
else {
doInvokeListener(listener, event);
}
}private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
// 将事件传入listener,完成事件的监听回调
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
// ...
}
}

onRefresh()

这是个空方法,交给子类实现。这里可以用来初始化特定上下文子类中的其他特殊 bean,也是留出来的一个扩展口。

/**
* Template method which can be overridden to add context-specific refresh work.
* Called on initialization of special beans, before instantiation of singletons.
*
* 可以重写以添加特定于上下文的刷新工作的模板方法。在单例实例化之前调用特殊 bean 的初始化。
*
* <p>This implementation is empty.
* @throws BeansException in case of errors
* @see #refresh()
*/
protected void onRefresh() throws BeansException {
// For subclasses: do nothing by default.
}

registerListeners()

上一步已经初始化完成了广播器,那接下来就是检查侦听器并注册它们。

事件可以按照注册的类型进行区分,可以分为以下三种:

  • 通过addApplicationListener()手动添加进去的
  • 容器里实现了ApplicationListener接口的
  • 容器启动早期需要的事件earlyApplicationEvents,早期事件是需要在这里直接发布的
/**
* Add beans that implement ApplicationListener as listeners.
* Doesn't affect other listeners, which can be added without being beans.
*
* 添加实现 ApplicationListener 的 bean作为侦听器。
* 不影响其他监听器,可以添加而不是 bean。
*/
protected void registerListeners() {
// Register statically specified listeners first.
// 首先注册静态指定的监听器,也就是通过addApplicationListener(ApplicationListener<?> listener) 注册的listener。
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
// 这里只是获取beanName,是为了避免初始化 bean 导致后置处理器失效
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
// 逐个注册listener
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}// Publish early application events now that we finally have a multicaster...
// 发布早期应用程序事件,因为我们终于有了一个广播器......
// 忍辱负重,早期事件存到了这里才能进行发布,因为之前没有广播器
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
// 逐个发布事件
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}

finishBeanFactoryInitialization(beanFactory)

准备工作已经基本完成,接下来就到了finishBeanFactoryInitialization(beanFactory)方法了。从方法名可以看到,这个方法是负责完成此上下文的 bean 工厂的初始化,初始化所有剩余的单例 bean。可以看到这个方法开始也进行了一些准备工作,例如注册类型装换器、占位符处理器以及LoadTimeWeaverAware加载等。最后会调用beanFactory.preInstantiateSingletons()进行对象创建,由于这里是比较复杂的过程,会分几篇文章去详细分析,这篇文章就是大概从表面上走完refresh()方法的源码。

/**
* Finish the initialization of this context's bean factory,
* initializing all remaining singleton beans.
*
* 完成此上下文的 bean 工厂的初始化,初始化所有剩余的单例 bean。
*
*/
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
// 初始化一个ConversionService用于类型转换,这个ConversionService会在实例化对象的时候用到
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
// 添加一个StringValueResolver,用于处理占位符,可以看到,默认情况下就是使用环境中的属性值来替代占位符中的属性
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
// 创建所有的LoadTimeWeaverAware
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}// Stop using the temporary ClassLoader for type matching.
// 静态织入完成后将临时的类加载器设置为null,所以除了创建LoadTimeWeaverAware时可能会用到临时类加载器,其余情况下都为空
beanFactory.setTempClassLoader(null);// Allow for caching all bean definition metadata, not expecting further changes.
// 将所有的配置信息冻结
beanFactory.freezeConfiguration();// Instantiate all remaining (non-lazy-init) singletons.
// 开始进行真正的创建
beanFactory.preInstantiateSingletons();
}

finishRefresh()

到这里容器已经准备好了,bean也已经实例化完成,就差最后的一些事件通知和后续的兜底处理。这里比较重要的是会调用到所有实现了LifecycleProcessor#onRefresh()的Bean,在这里可以让生命周期Bean实现很多扩展。其次比较重要的是会发布一个ContextRefreshedEvent事件,通知所有监听器容器已经启动完成,这里就可以实现一些容器启动完成后的回调或者是一些任务等,任君发挥。

/**
* Finish the refresh of this context, invoking the LifecycleProcessor's
* onRefresh() method and publishing the
* {@link org.springframework.context.event.ContextRefreshedEvent}.
*
* 完成容器的刷新启动,调用所有 LifecycleProcessor#onRefresh() 方法来发布 ContextRefreshedEvent 事件
*
*/
protected void finishRefresh() {
// Clear context-level resource caches (such as ASM metadata from scanning).
// 清除容器上下文级别的资源缓存(例如ASM扫描的元数据)
clearResourceCaches();// Initialize lifecycle processor for this context.
// 初始化上下文的 lifecycle processor
initLifecycleProcessor();// Propagate refresh to lifecycle processor first.
// 首先将刷新传播到生命周期处理器。
getLifecycleProcessor().onRefresh();// Publish the final event.
// 发布最终事件。
publishEvent(new ContextRefreshedEvent(this));// Participate in LiveBeansView MBean, if active.
// 参与 LiveBeansView MBean(如果处于活动状态)。
LiveBeansView.registerApplicationContext(this);
}

总结

本文的重点有点分散,更像是走马观花,但是分散里的重点毫无疑问是理解和区分BeanFactoryPostProcessorBeanPostProcessor之间的区别,文章开头通过一个例子去类比了一下这二者的作用阶段和分别可以完成什么工作,个人觉得还是比较贴切的,希望能够帮助到理解。

到这里已经基本把refresh()方法走了一遍,当然这里看到的大部分都是一些基础准备工作,最关键的Bean实例化是还没有开始分析的,Bean的实例化会后续分好几篇文章继续去分析。

今天这篇文章是比较简单的,没有太多逻辑,基本上都是一个一个小方法,嵌套不深,因为深入的我都不写了哈哈。

这系列写到这里,才完成了准备工作,接下来的Bean创建才是真正开始了重头戏。那接下来继续慢慢分析吧。

如果有人看到这里,那在这里老话重提。与君共勉,路漫漫其修远兮,吾将上下而求索。

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,905
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,430
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,247
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,058
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,690
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,727