港真,除了 awsl 我一概不知!
本文主题
Hi 各位周末好呀,我是野区 JC。难得周末有空余的时间,心心念念想把 Spring Boot 源解系列不断去完善。那么今天想去回顾一个老得掉牙但面试官他老人家问也问不腻的知识点,那就是Spring 的 Bean 配置读取加载入口与框架启动的流程 { refresh 方法 }
阅读本文的正确姿势
在之前我自己写过几篇源解的文章,深深地感到了文章内贴代码的恐惧,因为有些源码是没办法跳过的,很有可能因为一个细节代码没体现出来,读者就在中途瓦特了。但源解类型的文章贴代码是无可避免的,所以我尝试先准备一个概要,然后通过**链接跳转**的方式进行阅读源码。希望这种方式能够让你们有个更加清晰,阅读文章的脉络。整体流程
写文章之前特意画了一个执行图,但是由于篇幅过长,导致没办法体现在文章单中。所以只能使用表格来代替了。
可以观看以下表格,对这个方法做了什么有个基本的概念。
| 方法[method] | 作用[effect] |
|---|---|
| 1⃣ prepareRefresh() | 设置必备的环境变量,例如 servletConfig/ServletContext |
| 2⃣ obtainFreshBeanFactory() | 设置 BeanFactory 序列化 ID/获取 BeanFactory |
| 3⃣ prepareBeanFactory() | 把 BeanFactory 必要的配置准备好 |
| 4⃣ postProcessBeanFactory() | 模板方法,预留方法给子类修改 context 内部 BeanFactory. 了解 AnnotationConfigReactiveWebServerApplicationContext |
| 5⃣ invokeBeanFactoryPostProcessors() | 在此处统一调用 BeanFactoryPostProcessors 的方法 |
| 6⃣ registerBeanPostProcessors() | 注册 BeanProcessors,并调用其方法 |
| 7⃣ initMessageSource() | 初始化国际化相关的属性 |
| 8⃣ initApplicationEventMulticaster() | 初始化广播器 |
| 9⃣ onRefresh() | 预留特定的子类初始化特定的 Bean,通俗来说就是扩展 |
| 1⃣0⃣ registerListeners() | 注册监听器 |
| 1⃣1⃣ finishBeanFactoryInitialization() | 初始化所有剩下的单例 Bean |
| 1⃣2⃣ finishRefresh() | 发布 ContextRefresedhEvent 完成事件/JMX 相关处理 |
prepareRefresh()
prepareRefresh 方法是在做准备。做什么准备呢?
- 主要是容器的状态设置
- 初始化一些属性
- 检查必备的属性设置
protected void prepareRefresh() {
// closed 和 active 为 context 的两个状态
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
// ...省略日志代码
// 初始化 context 环境的参数,例如 ServletConfig / ServletContext 的参数
initPropertySources();
// 检察环境是否具备了一些必须加载的参数
getEnvironment().validateRequiredProperties();
// 保存在 refresh 方法之前加载的监听器;
// 如果没有,就将 applicationListeners 添加进 earlyApplicationListeners
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// 重置自带的应用监听器到还没有 refresh 前的状态
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// 设为空
this.earlyApplicationEvents = new LinkedHashSet<>();
}
上面代码 getEnvironment().validateRequiredProperties() 这个值得我们注意一点。如果你的应用里面,有一个必须配置的/不可或缺的配置参数,那么 Spring 提供了这方面的检测。
obtainFreshBeanFactory()
这个方法主要是为了获取一个 BeanFactory。聪明的你们应该知道,这里绝对是一个扩展点。这里即可以通过平台自由的实现,也可以自己实现。所以明显,refreshBeanFactory 和 getBeanFactory 方法是预留给子类实现的模板方法。protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
prepareBeanFactory()
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 保持 context 的 classLoader 和 beanFactory 一样
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// 通过上下文(context)回调来配置 BeanFactory
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
// BeanFactory 不会注册的一些类型(不会去实例化),因为接下来有代码会进行配置并实例化
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// 这是为了注册一些配置的 ApplicationListeners,例如 spring.factories/实现了 ApplicationListener 的类/从 SpringApplication.addApplicationListener() 添加进来的类
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// 检测 LoadTimeWeaver 和准备去编织,跟 AOP 有关
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// 为了类型的匹配,设置一个临时的 classloader (后面会清除掉的)
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// 注册默认的环境类
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
postProcessBeanFactory()
postProcessBeanFactory 方法在 AbstractApplicationContext 里是一个模板方法,预留给子类进行扩展的。在 Spring Boot 中,其子类 AnnotationConfigReactiveWebServerApplicationContext 实现了该方法进行扩展,我们可以看看它做了哪些事情@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 调用父类的方法
super.postProcessBeanFactory(beanFactory);
// 根据路径进行扫描加载类
if (!ObjectUtils.isEmpty(this.basePackages)) {
this.scanner.scan(this.basePackages);
}
// 根据传入的注解类进行注册
if (!this.annotatedClasses.isEmpty()) {
this.reader.register(ClassUtils.toClassArray(this.annotatedClasses));
}
}
上面的代码说了两个知识点
-
在 Spring Boot 中,我们可以通过 basePackages 来指定扫描的包路径。例如
@SpringBootApplication(scanBasePackages = {"com.jc.demov20200215"}) public class Demov20200215Application { public static void main(String[] args) { SpringApplication.run(Demov20200215Application.class, args); } }上面的 com.jc.demov20200215 就是我们指定扫的包。如果有多个的话,可以使用逗号进行分割
-
this.annotatedClasses是指具有 @Configuration 注解的类,可以通过硬代码进行扩展
invokeBeanFactoryPostProcessors()
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// 这里的处理委托给了 PostProcessorRegistrationDelegate 类
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// 检测LoadTimeWeaver并准备编织
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
从上面的代码我们知道,context 将调用 beanFactory 的 委托给了 PostProcessorRegistrationDelegate。这里面的核心方法主要是调用 BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry()。但是由于加入了 PriorityOrdered[优先级]/Ordered[顺序] 等接口用于对调用的顺序进行干扰,所以需要分别检测和调用,代码就变得稍微有点长了。所以,我在这里仅仅是做一个流程的解释。这个流程一共分为三部分:
part 1:
- 遍历 beanFactoryPostProcessors,查看是否实现了 BeanDefinitionRegistryPostProcessor 接口
- 是,则调用 postProcessBeanDefinitionREgistry,并添加至 registryProcessors 集合中
- 否,添加到集合 registryPostProcessors
part 2:
- 遍历 beanFactoryPostProcessors,查看是否实现了 ProrityOridered 接口
- 是,则调用 postProcessBeanDefinitionREgistry,并添加至 currentRegistryProcessors 集合中,把 beanName 添加进 processedBeans
- 对 currentRegistryProcessors 集合进行排序
- 将 registryProcessors 里的 BeanFactoryPostProcessor 添加到 registryProcessors,然后调用 registryProcessors 里面的 BeanFactoryPostProcessor
- 清空 currentRegistryProcessors
part 3:
- 遍历 beanFactoryPostProcessors,查看是否实现了 Ordered 接口
- 是,则调用 postProcessBeanDefinitionREgistry,并添加至 currentRegistryProcessors 集合中,把 beanName 添加进 processedBeans
- 对 currentRegistryProcessors 集合进行排序
- 将 registryProcessors 里的 BeanFactoryPostProcessor 添加到 registryProcessors,然后调用 registryProcessors 里面的 BeanFactoryPostProcessor
- 清空 currentRegistryProcessors
part 4:
第 4 part 和第 2 / 第 3 差不多,都会不断循环 beanFactoryPostProcessors,保证所有的 BeanFactoryPostProcessor 都能够被调用(有可能期间有 beanFactoryPostProcessors 被添加进来),直到完成为止。
part 5:
接下来开始调用所有 processors 的 postProcessBeanFactory 回调方法。 Spring 会循环 beanFactoryPostProcessors,然后根据 PriorityOrdered / Ordered / 没有实现任何接口的 BeanFactoryPostProcessor 进行分类。然后再以上面分类的顺序,分别进行排序,调用。
ps:具体代码请打开折叠标签 ⬇ ️
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// 调用 BeanDefinitionRegistryPostProcessors
Set<String> processedBeans = new HashSet<>();
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// 首先,调用实现了PriorityOrdered 的 BeanFactoryPostProcessors
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 然后调用实现了 Ordered 的 BeanFactoryPostProcessors
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// 最后调用其他的BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// 清除元数据
beanFactory.clearMetadataCache();
}
registerBeanPostProcessors()
这个方法主要是注册 BeanPostProcessor。BeanPostProcessor 是什么呢?这里稍微普及一下,BeanPostProcessor 是 Spring 框架预留出来的扩展点。它有两个方法 postProcessBeforeInitialization 和 postProcessAfterInitialization。当 Spring 进行实例化的时候,会根据 Bean 是否实现了 BeanPostProcessor 进行调用这两个方法。也就是,BeanPostProcessor 可以影响得到最终实例化的效果。例如说,AOP 的动态代理就是在 postProcessAfterInitialization 方法实现了;又例如,标记接口这种处理会在 postProcessBeforeInitialization 进行的。所以这个就是为了接下来调用而提前进行一个注册。详细了解可以去官网康康 : Container Extension Points
方法里面的代码是这样的。
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
和上面的 invokeBeanFactoryPostProcessors 一样,实际上委托给了 PostProcessorRegistrationDelegate 进行处理。所以我讲一下思路
- 首先,从 BeanFactory 中拿到所有实现了 BeanPostProcessor 的子类
- 接下来要进行分类。分类的条件是实现 PriorityOrdered 接口 / 实现了 PriorityOrdered 接口 / 什么都没实现的。
- 然后分别对三大类进行排序,并注册到 beanFactory 中。
ps:具体代码请打开折叠标签 ⬇ ️
PostProcessorRegistrationDelegate.registerBeanPostProcessors()
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
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;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// 根据 实现了 PriorityOrdered / 实现了 Ordered / 什么都没实现的
// 进行分类
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);
}
}
// 注册实现了 PriorityOrdered 的 BeanPostProcessors
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// 注册实现 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);
// 注册正常(没实现 PriorityOrdered/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);
// 最后,重复注册 Spring 内部的 BeanPostProcessors
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// 检测在 ApplicationListeners 内的 Bean 来注册
// moving it to the end of the processor chain (for picking up proxies etc).
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
initMessageSource()
初始化国际化语言protected void initMessageSource() {
// 获取容器
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 查看有没有国际化语言的类
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
if (hms.getParentMessageSource() == null) {
// 如果没有父 MessageSource 就设置上下文为父 MessageSource
hms.setParentMessageSource(getInternalParentMessageSource());
}
}
// ...省略日志打印代码
}
else {
// 防止空指针,使用空的 MessageSource 来接受 getMessage 的调用
DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
// 注册进 beanFactory
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
// ...省略日志打印代码
}
}
initApplicationEventMulticaster()
这里讲的是初始化广播器。我之前有篇文章监听者模式在 Spring Boot已经说过这方面的知识,可以去康康!
protected void initApplicationEventMulticaster() {
// 将 beanFactory 转为 ConfigurableListableBeanFactory
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 查看是否应用级别的广播器
// 有,就复制给当前的 applicationEventMulticaster 属性
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
//
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
// 省略代码
}
else {
// 无,就进行实例化
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
// 注册到 beanFactory
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
// 省略代码
}
}
onRefresh()
onRefresh 方法也是预留给子类进行实现。而这次实现该方法的是其子类 ReactiveWebServerApplicationContext。在其子类实现呢,主要是为了实例化一个外部容器来运行项目,例如 tomcat / jetty 。这里不展开讲。有兴趣可以去看下,这里不展开来讲。 protected void onRefresh() {
// 调用父类的方法
super.onRefresh();
try {
// 创建 web 容器
createWebServer();
}
catch (Throwable ex) {
// ...
}
}
registerListeners()
注册监听器
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!
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// 发布早期没有被发布的事件[event]
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
在初始化 context 的过程中,如果有事件[event]被发布的话,会暂时存储在 this.earlyApplicationEvents 属性当中,等到 registerListeners 的时候重新通过广播器发布。
finishBeanFactoryInitialization()
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 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));
}
// 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.
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// 停止为了类型匹配使用临时的 classloader
beanFactory.setTempClassLoader(null);
// 缓存所有 bean defition 的元数据,接下来都不让改变了
beanFactory.freezeConfiguration();
// 实例化所有剩余的单例
beanFactory.preInstantiateSingletons();
}
finishRefresh()
下面是 finishRefresh,对 refresh 方法做一个最后的收尾。protected void finishRefresh() {
// 清除 上下文(context)级别的资源缓存(例如扫描包存储的 ASM 元数据)
clearResourceCaches();
// 为当前上下文初始化 lifecycle processor
initLifecycleProcessor();
// 调用 lifecycle processor 的 refresh 方法
getLifecycleProcessor().onRefresh();
// 发布上下文(context) 初始化完毕事件
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
LiveBeansView.registerApplicationContext(this);
}
有一个细节或许你们没注意到?
Spring 的源码给我的感觉就是挺遵守一些设计模式的规范的,例如扩展,例如细节处理。这些规范同时给了我们这些使用者很大的灵活性,能够快速地修改响应自己的需求。在阅读源码,我发现 refresh 方法是中,this.startupShutdownMonitor 是被关键字 synchronized 所同步的。那就意味着,连上下文[context]即使是第一次启动之后,还可以修改配置文件进行反复重启,相当于“热更新”的效果。真的挺不错的。结语
其实今天记录的文章难度 ❤❤。我个人觉得这个是 Spring 之中非常核心的一个方法,因为在我们探究的过程中,看得到它为启动一个基本的框架做了多少的工作,可想而知整体来说负责的工作其实挺多的。同时我想说这是一个入门去学习怎么看源码/从中吸取框架思想的一个很好的切入点,值得我们去探究和反复细品。ok 结束!如果对于你们的学习以及成长有所帮助的话,{今天点赞加关注,未来一起去进步}!❤️