点击右上角“关注”,跟我一起深入分析、学习SpringBoot最新版本源码!
系列文章:
源码解析(一):SpringBoot是怎么启动的?(基于最新版2.2.0)
源码解析(二):SpringBoot是如何一步步加载监听器的?
上篇我们主要讲述了SpringBoot-2.2.0.RELEASE版本在启动过程中是如何一步步的从META-INF/spring.factories文件中加载到所有的监听器并通过反射实例化成监听器示例。
全篇讲解的就一句代码:
今天我们继续分析下一句代码:
当SpringBoot成功获取到所有已配置的监听器之后是如何启动这些监听器的呢?
让我们一起进入starting()这个方法的源码中去,点击starting方法进入如下源码:
starting方法就是循环的执行每一个监听器的方法,点击listener.starting()方法进入实现类EventPublishingRunListener的starting方法:
EventPublishingRunListener
EventPublishingRunListener这个类是什么时候初始化的呢?
肯定是在我们要分析的
listeners.starting()
方法之前对吧,否则这个starting方法是无法执行的。
我们先看看这个类的继承关系、成员变量以及构造方法:
然后我们需要找到初始化这个类的时机,在构造方法里打好断点,启动项目,从启动类开始执行进来。
如果大家看了上篇源码解析(二):SpringBoot是如何一步步加载监听器的?,一步步debug就会找到这个EventPublishingRunListener类,通过反射的方式获取其实例:
然后通过构造方法设置好这个类的每一个参数,从上图我们可以看到SpringApplication启动类的详细信息。
其中的initialMulticaster是一个广播器,初始化EventPublishingRunListener的时候,将之前加载到SpringApplication中的监听器设置到这个广播器里面,以便执行下一步listener.start()方法:
每一个监听器都会广播一个事件,广播器负责根据不同的场景广播不同的事件,阅读源码可以发现可以广播如下这些事件:
而监听器实现了ApplicationListener接口,初始化EventPublishingRunListener时候,通过广播器把这些监听器添加到ApplicationListener,这样监听器initialMulticaster.multicastEvent就触发了监听器的事件:
看见了listener.onApplicationEvent(event);是不是很熟悉?
我们平时实现自己实现一个listener是不是也要实现这个方法?
监听器加载的时候是不是就自动执行这个方法了?
分析到这里是不是就知道了SpringBoot在启动的时候是如何加载监听器并执行这些监听器里面的onApplicationEvent方法了?
我们从META-INF/spring.factories中:
找一个监听了ApplicationEvent事件的监听器LoggingApplicationListener看看:
在这个listener的onApplicationEvent方法设置断点,debug启动时候大家可以发现当执行listeners.starting();这句代码的时候,一旦执行
this.initialMulticaster.multicastEvent
广播器广播事件时候,便立即进入监听器的onApplicationEvent方法中去执行监听器的实现逻辑。
这样通过getRunListeners()方法获取的监听器就通过listeners.starting()方法全部执行完毕了。
但是此处只是执行监听了ApplicationEvent事件的监听器。这些预先执行的监听器其实还是为了下一步创建spring容器做好准备工作。
实际上监听器的执行会伴随着整个SpringBoot的启动过程。根据不同的事件类型来执行不同的监听器,但是流程都是上述分析的流程,都是通过initialMulticaster广播器来广播监听器监听的事件,你一广播,我这个监听器就立即执行,基于事件驱动的思想!
大家在平时写代码的过程中有采用过事件驱动的编程方式吗?
下次为大家继续分析SpringBoot源码的Spring容器准备、启动环节。