一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情。
前篇导航
Spring 源码阅读笔记(一)
Spring 源码阅读笔记(二)
Spring 源码阅读笔记(三)
Spring 源码阅读笔记(四)
Spring 源码阅读笔记(五)
Spring 源码阅读笔记(六) 主线 registerBeanPostProcessors解读
Spring 源码阅读笔记(七) 支线 getBean方法解读
Spring 源码阅读笔记(八) 支线createBean方法解读
Spring 源码阅读笔记(九) 主线 initMessageSource方法解读
前篇回顾
上一篇文章的方法比较简单,只是设置了一个Message的值,没什么太大的实际意义,我看到只是设置了ApplicationContext中的一个MessageSource对象。写的有点水,我自我反省一下,后面准备把第九章删除,回炉重造一篇。
接下来看一下方法调用关系图,里面会有今天文章中涉及到的几个方法。
正式开始
initApplicationEventMulticaster
这段代码粗略扫一眼,发现和上一个方法,并没有什么两样。为当前的ApplicationContext设置了一个applicationEventMulticaster属性。这里暂时不知道他是干嘛的。
onRefresh
// Initialize other special beans in specific context subclasses.
// 初始化特定上下文子类中的其他特殊 bean。
onRefresh();
protected void onRefresh() throws BeansException {
// For subclasses: do nothing by default.
}
看到这样的代码就很熟悉了,源码读下来遇到很多了,模版方法,方便扩展用的。看看他在哪些地方重写的。
简单一看都是web包下的,这里我们就不看了。
registerListeners
// Check for listener beans and register them.
// 检查侦听器 bean 并注册它们。
registerListeners();
看方法上方的注释是注册监听器,这里猜测一下是要通过BeanDefinition获取一些对象,然后放到application中的某个属性中,具体是不是呢,看一下代码。
protected void registerListeners() {
// Register statically specified listeners first.
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!
// 不要在此处初始化 FactoryBeans:我们需要保留所有常规 bean
未初始化让后处理器适用于他们!
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
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 (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
一进入方法先粗略看一遍,看到了一个熟悉的东西。getApplicationEventMulticaster,一看这个不是刚刚在上面初始化的事件多播器嘛,那么就看明白了,所谓的ApplicationEventMulticaster是一个观察者模式,这里的把所有的监听器注册到多播器中,多播器等到调用的时候回去invoke他们的方法。
第一个For
第一个for循环是用来添加Spring内部自带的监听器,我们这里没有配置,所以是没有的。
第二个For
第二个for循环是用来添加我们自己创建ApplicationListener,根据上方的注释可以看到,在这里不允许创建Bean的实例,所以这里没有调用getBean,而是选择获取了BeanName,然后存入多播器中,等待机会初始化。至于自定义ApplicationListener可以用来做什么这里就不做科普了,感兴趣的可以自己搜索。
第三个For
Publish early application events now that we finally have a multicaster...
发布早期应用程序事件,因为我们终于有了一个多播器......
这里大概的意思是,获取早期的事件,然后广播一下,也就是for循环一下这个早期事件列表,然后invoke他们的方法。
finishBeanFactoryInitialization
// Instantiate all remaining (non-lazy-init) singletons.
// 实例化所有剩余的(非惰性初始化)单例。
finishBeanFactoryInitialization(beanFactory);
这里根据上方的注释看出,这方法是把剩余没有实例化的Bean对象在这里都实例化。
先来看一下内部方法的具体源代码,由于方法过长,这里还是选择分段食用。
finishBeanFactoryInitialization 第一段
// Initialize conversion service for this context.
// 为此上下文初始化转换服务。
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));
}
这里需要先看一下这个if的条件,第一个条件很简单,就是工厂中是否有这个对象,不管是那个工厂有这个对象,这里都会返回true,第二个方法意思就是,既然你这个Bean存在,那你这个对象是不是和我给的类型是一样的。
那么两个条件都为true的话,那就要给BeanFactory设置这个conversionService了,虽然我还不知道他是干嘛的。
finishBeanFactoryInitialization 第二段
// Register a default embedded value resolver if no BeanFactoryPostProcessor
// (such as a PropertySourcesPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
// 如果之前没有注册过任何 BeanFactoryPostProcessor
//(例如 PropertySourcesPlaceholderConfigurer bean),
// 则注册一个默认的嵌入值解析器:此时,主要用于解析注释属性值。
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
说真话,没看懂这个方法是干嘛的,先跳过。
finishBeanFactoryInitialization 第三段
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
// 尽早初始化 LoadTimeWeaverAware bean,以便尽早注册它们的转换器。
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
这一段代码比较简单,获取继承自LoadTimeWeaverAware接口BeanName,随后去创建了这些Bean,搞不明白为什么GetBean是创建Bean的方法,可以翻阅一下我之前发布的文章。
finishBeanFactoryInitialization 第四段
// Stop using the temporary ClassLoader for type matching.
// 停止使用临时 ClassLoader 进行类型匹配。
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
// 允许缓存所有 bean 定义元数据,而不是期望进一步的更改。
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
// 实例化所有剩余的(非惰性初始化)单例。
beanFactory.preInstantiateSingletons();
看这一段代码,一行一个注释很明显可以看出这个方法是干嘛,我就不介绍了,这里可以看到最重要的应该就是最后一个方法了,我们重点关注一下。
其实方法很简单,把当前Bean工厂中从Xml解析出来的BeanDefinitionName全部拿出来,然后挨个遍历调用GetBean(beanName)方法。
finishRefresh
protected void finishRefresh() {
// Clear context-level resource caches (such as ASM metadata from scanning).
// 清除上下文级别的资源缓存(例如扫描中的 ASM 元数据)。
clearResourceCaches();
// Initialize lifecycle processor for this context.
// 为此上下文初始化生命周期处理器。
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
// 首先将刷新传播到生命周期处理器。
getLifecycleProcessor().onRefresh();
// Publish the final event.
// 发布最终事件。
publishEvent(new ContextRefreshedEvent(this));
}
每行一个注释,可以看到方法大致是做什么的。这里就不一一解释了。基本上都可以猜到里面做了什么操作。
告一段落
这篇文章到这里就结束啦,那么整个Spring的源码解读下来,好像没有发现对注解解析,后面会开文章作为支线为大家讲解。可能很多人会疑惑,为什么我没有讲Bean的循环依赖,Bean生命周期什么的,其实跟着我的一篇篇文章阅读下来后,即使我这里没有讲解,大家可能都有一个印象了。这个时候大家再去看Spring的架构图,可能会有更深刻的认识。
都看到这了,点个赞再走呗,宝~
结束语
写文章的目的是为了帮助自己巩固知识,写的不好或者错误的地方可以在评论区指出。如果您看了文章觉得对您有所帮助可以点个赞,如果发现有些问题产生了疑惑,或者不明白的可以评论、加我微信,一定知无不言。当然也希望和大家交个朋友,相互学习。