Spring 源码阅读笔记 (十) 主线终章 Refresh中全部方法解读。

772 阅读7分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情

前篇导航

Spring 源码阅读笔记(一)
Spring 源码阅读笔记(二)
Spring 源码阅读笔记(三)
Spring 源码阅读笔记(四)
Spring 源码阅读笔记(五)
Spring 源码阅读笔记(六) 主线 registerBeanPostProcessors解读
Spring 源码阅读笔记(七) 支线 getBean方法解读
Spring 源码阅读笔记(八) 支线createBean方法解读
Spring 源码阅读笔记(九) 主线 initMessageSource方法解读

前篇回顾

上一篇文章的方法比较简单,只是设置了一个Message的值,没什么太大的实际意义,我看到只是设置了ApplicationContext中的一个MessageSource对象。写的有点水,我自我反省一下,后面准备把第九章删除,回炉重造一篇。

接下来看一下方法调用关系图,里面会有今天文章中涉及到的几个方法。 image.png

正式开始

initApplicationEventMulticaster

image.png 这段代码粗略扫一眼,发现和上一个方法,并没有什么两样。为当前的ApplicationContext设置了一个applicationEventMulticaster属性。这里暂时不知道他是干嘛的。

onRefresh

// Initialize other special beans in specific context subclasses.
// 初始化特定上下文子类中的其他特殊 bean。
onRefresh();


protected void onRefresh() throws BeansException {
   // For subclasses: do nothing by default.
}

看到这样的代码就很熟悉了,源码读下来遇到很多了,模版方法,方便扩展用的。看看他在哪些地方重写的。 image.png 简单一看都是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

image.png 第一个for循环是用来添加Spring内部自带的监听器,我们这里没有配置,所以是没有的。

第二个For

image.png 第二个for循环是用来添加我们自己创建ApplicationListener,根据上方的注释可以看到,在这里不允许创建Bean的实例,所以这里没有调用getBean,而是选择获取了BeanName,然后存入多播器中,等待机会初始化。至于自定义ApplicationListener可以用来做什么这里就不做科普了,感兴趣的可以自己搜索。

第三个For

image.png

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();

看这一段代码,一行一个注释很明显可以看出这个方法是干嘛,我就不介绍了,这里可以看到最重要的应该就是最后一个方法了,我们重点关注一下。

image.png 其实方法很简单,把当前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的架构图,可能会有更深刻的认识。

image.png

都看到这了,点个赞再走呗,宝~

结束语

写文章的目的是为了帮助自己巩固知识,写的不好或者错误的地方可以在评论区指出。如果您看了文章觉得对您有所帮助可以点个赞,如果发现有些问题产生了疑惑,或者不明白的可以评论、加我微信,一定知无不言。当然也希望和大家交个朋友,相互学习。