目录
一、背景
上一篇我们讲到SpringApplication对象创建,现在开始SpringApplication的run方法,run方法就不是一句话就能讲完的,不然你也太小看这个框架了,我们需要开始分步解读了,不管总样,我们要先总体上对整个流程有个大概的了解,这不我已经为大家准备好了。
package com.alian.springboot;
import com.alian.springboot.service.HelloWorld;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(HelloWorld.class, args);
}
}
1.1、run方法整体流程
接下来的几个方法所在类的具体路径:org.springframework.boot.SpringApplication
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class<?>[] { primarySource }, args);
}
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}
public ConfigurableApplicationContext run(String... args) {
// 1、记录启动的开始时间(单位纳秒)
long startTime = System.nanoTime();
// 2、初始化启动上下文、初始化应用上下文
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
// 3、设置无头属性:“java.awt.headless”,默认值为:true(没有图形化界面)
configureHeadlessProperty();
// 4、获取所有 Spring 运行监听器
SpringApplicationRunListeners listeners = getRunListeners(args);
// 发布应用启动事件
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
// 5、初始化默认应用参数类(命令行参数)
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 6、根据运行监听器和应用参数 来准备 Spring 环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
// 配置忽略bean信息
configureIgnoreBeanInfo(environment);
// 7、创建 Banner 并打印
Banner printedBanner = printBanner(environment);
// 8、创建应用上下文
context = createApplicationContext();
// 设置applicationStartup
context.setApplicationStartup(this.applicationStartup);
// 9、准备应用上下文
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
// 10、刷新应用上下文(核心)
refreshContext(context);
// 11、应用上下文刷新后置处理
afterRefresh(context, applicationArguments);
// 13、时间信息、输出日志记录执行主类名
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
// 14、发布应用上下文启动完成事件
listeners.started(context, timeTakenToStartup);
// 15、执行所有 Runner 运行器
callRunners(context, applicationArguments);
} catch (Throwable ex) {
// 运行错误处理
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
// 16、发布应用上下文就绪事件(可以使用了)
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
listeners.ready(context, timeTakenToReady);
} catch (Throwable ex) {
// 运行错误处理
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
// 17、返回应用上下文
return context;
}
1.2、本文解读范围
本文主要讲解到监听器的启动,也就是:
public ConfigurableApplicationContext run(String... args) {
// 1、记录启动的开始时间(单位纳秒)
long startTime = System.nanoTime();
// 2、初始化启动上下文、初始化应用上下文
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
// 3、设置无头属性:“java.awt.headless”,默认值为:true(没有图形化界面)
configureHeadlessProperty();
// 4、获取所有 Spring 运行监听器
SpringApplicationRunListeners listeners = getRunListeners(args);
// 发布应用启动事件
listeners.starting(bootstrapContext, this.mainApplicationClass);
//本文解析到此处,其他代码省略
}
二、记录应用启动的开始时间
首先是下面这段代码
// 1、记录应用程序启动的开始时间(单位纳秒)
long startTime = System.nanoTime();
以前的版本(比如 2.5.2)是:
// 1、创建并启动计时监控类
StopWatch stopWatch = new StopWatch();
stopWatch.start();
哇,相比之前版本的,终于简洁了(一个简单的事,简单处理就好了)!!!这里记录了应用程序启动的开始时间。
三、初始化启动上下文
接下来是下面这段代码
// 2、初始化启动上下文、初始化应用上下文
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
3.1、初始化启动上下文
此方法所在类的具体路径:org.springframework.boot.SpringApplication
private DefaultBootstrapContext createBootstrapContext() {
//创建 DefaultBootstrapContext实例
DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();
//遍历列表 列表内容:bootstraptInitializer 注册表初始器
//每个注册表初始器初始化引导程序上下文
this.bootstrapRegistryInitializers.forEach((initializer) -> initializer.initialize(bootstrapContext));
return bootstrapContext;
}
从上一篇文章知道并没有获取到启动上下文初始化器,即bootstrapRegistryInitializers的大小为0,也就是没有初始化器执行。我们看下创建 DefaultBootstrapContext实例做了什么,进入 org.springframework.boot.DefaultBootstrapContext
public class DefaultBootstrapContext implements ConfigurableBootstrapContext {
private final Map<Class<?>, InstanceSupplier<?>> instanceSuppliers = new HashMap<>();
private final Map<Class<?>, Object> instances = new HashMap<>();
//在里面实例化了一个应用程序事件广播器
private final ApplicationEventMulticaster events = new SimpleApplicationEventMulticaster();
}
3.2、初始化应用程序事件广播器
在这里实例化了一个SimpleApplicationEventMulticaster,它继承了抽象类ApplicationEventMulticaster 。
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
public SimpleApplicationEventMulticaster() {
}
}
实例化SimpleApplicationEventMulticaster也会对父类进行初始化,我们继续查看ApplicationEventMulticaster 做了什么。
public abstract class AbstractApplicationEventMulticaster
implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware {
//实例化DefaultListenerRetriever,实际就是一个内部类
private final DefaultListenerRetriever defaultRetriever = new DefaultListenerRetriever();
final Map<ListenerCacheKey, CachedListenerRetriever> retrieverCache = new ConcurrentHashMap<>(64);
//一个内部类
private class DefaultListenerRetriever {
public final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();
public final Set<String> applicationListenerBeans = new LinkedHashSet<>();
public Collection<ApplicationListener<?>> getApplicationListeners() {
List<ApplicationListener<?>> allListeners = new ArrayList<>(
this.applicationListeners.size() + this.applicationListenerBeans.size());
allListeners.addAll(this.applicationListeners);
if (!this.applicationListenerBeans.isEmpty()) {
BeanFactory beanFactory = getBeanFactory();
for (String listenerBeanName : this.applicationListenerBeans) {
try {
ApplicationListener<?> listener =
beanFactory.getBean(listenerBeanName, ApplicationListener.class);
if (!allListeners.contains(listener)) {
allListeners.add(listener);
}
}
catch (NoSuchBeanDefinitionException ex) {
// Singleton listener instance (without backing bean definition) disappeared -
// probably in the middle of the destruction phase
}
}
}
AnnotationAwareOrderComparator.sort(allListeners);
return allListeners;
}
}
}
接下来事件发布时会用到这些:DefaultListenerRetriever、retrieverCache、SimpleApplicationEventMulticaster 。
3.3、初始化应用上下文
ConfigurableApplicationContext context = null;
这里仅仅是定义了这个对象,此这个context 贯穿了整个容器,后续的创建、准备、刷新等等都离不开它,是一个非常核心的容器。
四、设置无头属性
接下来是下面这段代码
// 3、设置无头属性:“java.awt.headless”,默认值为:true(没有图形化界面)
configureHeadlessProperty();
4.1、设置无头属性
此方法所在类的具体路径:org.springframework.boot.SpringApplication
private boolean headless = true;//默认值为true
private static final String SYSTEM_PROPERTY_JAVA_AWT_HEADLESS = "java.awt.headless";
private void configureHeadlessProperty() {
System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,
System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
}
给系统属性java.awt.headless设置值,可以自定义设定,如果没有设定则使用默认值true。 java.awt.headless 是J2SE的一种模式,用于在缺少显示屏、键盘或者鼠标时的系统配置,很多监控工具如 jconsole 需要将该值设置为true,但对于服务器来说,可以不需要显示器,所以默认设置为true。
五、创建并发布运行监听器
最后是下面这段代码,也是本文中最重要的一段了
// 4、获取所有 Spring 运行监听器
SpringApplicationRunListeners listeners = getRunListeners(args);
// 发布应用启动事件
listeners.starting(bootstrapContext, this.mainApplicationClass);
5.1、获取所有运行监听器
此方法所在类的具体路径:org.springframework.boot.SpringApplication
public class SpringApplication {
private static final Log logger = LogFactory.getLog(SpringApplication.class);
private ApplicationStartup applicationStartup = ApplicationStartup.DEFAULT;
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
//初始化SpringApplicationRunListeners注意后面有个 s 哦,相当于SpringApplicationRunListener的一个集合
return new SpringApplicationRunListeners(logger,
getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args),
this.applicationStartup);
}
}
getSpringFactoriesInstances这个方法相信我们已经很熟悉了,在我们Alian解读SpringBoot 2.6.0 源码(一):SpringApplication对象创建(Spring工厂加载机制)就讲过了。这里获取到了一个事件发布运行监听器:EventPublishingRunListener,我们在spring-boot-2.6.0.jar 的META-INF/spring.factories 文件中找到如下配置
# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener
applicationStartup最终就是DefaultApplicationStartup,同时实例化了对象DefaultStartupStep,此对象的方法会在监听器调用starting中的doWithListeners方法用到。初始化SpringApplicationRunListeners注意后面有个 s 哦,相当于SpringApplicationRunListener的一个集合,它包含了运行监听器整个生命周期中执行的方法。
构造方法所在类的具体路径:org.springframework.boot.SpringApplicationRunListeners
SpringApplicationRunListeners(Log log, Collection<? extends SpringApplicationRunListener> listeners,
ApplicationStartup applicationStartup) {
this.log = log;
this.listeners = new ArrayList<>(listeners);
this.applicationStartup = applicationStartup;
}
5.2、开始启动事件发布运行监听器
接下里看下运行监听器的启动:
//运行监听器开始启动
listeners.starting(bootstrapContext, this.mainApplicationClass);
此方法所在类的具体路径:org.springframework.boot.SpringApplicationRunListeners,上一步的获取到的事件发布运行监听器,并且也通过构造方法赋值到SpringApplicationRunListeners的属性:private final List<SpringApplicationRunListener> listeners。
private final List<SpringApplicationRunListener> listeners;
void starting(ConfigurableBootstrapContext bootstrapContext, Class<?> mainApplicationClass) {
doWithListeners("spring.boot.application.starting", (listener) -> listener.starting(bootstrapContext),
(step) -> {
if (mainApplicationClass != null) {
step.tag("mainApplicationClass", mainApplicationClass.getName());
}
});
}
//5.1章节中已经讲过了
private void doWithListeners(String stepName, Consumer<SpringApplicationRunListener> listenerAction,
Consumer<StartupStep> stepAction) {
StartupStep step = this.applicationStartup.start(stepName);
//遍历运行监听器
this.listeners.forEach(listenerAction);
if (stepAction != null) {
stepAction.accept(step);
}
step.end();
}
因为我们只获取到了一个运行监听器也就是事件发布运行监听器:EventPublishingRunListener,所以listener.starting(bootstrapContext)就是执行事件发布运行监听器的启动。
5.3、事件发布运行监听器
我们看下 EventPublishingRunListener 的 starting 方法
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
private final SpringApplication application;
private final String[] args;
private final SimpleApplicationEventMulticaster initialMulticaster;
public EventPublishingRunListener(SpringApplication application, String[] args) {
this.application = application;
this.args = args;
this.initialMulticaster = new SimpleApplicationEventMulticaster();
for (ApplicationListener<?> listener : application.getListeners()) {
// 构造方法把之前获取到的监听器(8个)加入到事件广播器中(广播器调用时用到)
this.initialMulticaster.addApplicationListener(listener);
}
}
@Override
public void starting(ConfigurableBootstrapContext bootstrapContext) {
// 通过事件广播器
this.initialMulticaster
.multicastEvent(new ApplicationStartingEvent(bootstrapContext, this.application, this.args));
}
}
EventPublishingRunListener 的构造方法是很重要的,把之前SpringApplication对象创建时获取到的监听器加入到广播器中,后续广播器会用到,具体见章节5.5。
这里实际调用时通过简单应用程序事件广播器:SimpleApplicationEventMulticaster,并且实例化了一个应用程序启动事件:ApplicationStartingEvent,这里值得一说的是它的父类 SpringApplicationEvent,后续的事件大部分都是跟这个有关。
事件类型 | 说明 |
---|---|
ApplicationStartingEvent | 应用程序开始启动事件 |
ApplicationEnvironmentPreparedEvent | 应用程序环境准备事件 |
ApplicationPreparedEvent | 应用程序上下文准备事件 |
ApplicationContextInitializedEvent | 应用程序容器初始化事件 |
ApplicationStartedEvent | 应用程序启动完毕事件 |
ApplicationReadyEvent | 应用程序准备就绪事件 |
ApplicationFailedEvent | 应用程序失败事件 |
5.4、事件发布广播器
方法所在类的具体路径:org.springframework.context.event.SimpleApplicationEventMulticaster
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
@Override
public void multicastEvent(ApplicationEvent event) {
// 1、通过事件解析事件类型
// 2、广播事件
multicastEvent(event, resolveDefaultEventType(event));
}
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
// executor默认为null
Executor executor = getTaskExecutor();
// 1、根据事件和事件类型获取监听器列表
// 2、然后遍历监听器列表,分别调用监听器的方法
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
} else {
// 调用
invokeListener(listener, event);
}
}
}
}
- 首先根据事件解析事件的类型(这里的事件是ApplicationStartingEvent)
- 根据事件和事件类型进行事件广播
- 根据事件和事件类型获取事件监听器列表(重点)
我们看看根据事件和类型怎么获取符合条件的监听器,也就是 getApplicationListeners(event, type) 方法。
5.5、获取符合事件的监听器
这里调用getApplicationListeners方法,实际就是调用抽象类AbstractApplicationEventMulticaster中的getApplicationListeners方法。
protected Collection<ApplicationListener<?>> getApplicationListeners(
ApplicationEvent event, ResolvableType eventType) {
// event为ApplicationStartingEvent
// event里面的source就是SpringApplication,是在实例化ApplicationStartingEvent时赋值的
Object source = event.getSource();
Class<?> sourceType = (source != null ? source.getClass() : null);
// 静态内部类,也就是根据 event 类型和 source 类型构造出来的对象
ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);
// 要填充的CachedListenerRetriever
CachedListenerRetriever newRetriever = null;
// 此时是为null,retrieverCache在初始化应用程序事件广播器就初始化好了(见小章节3.2)
// retrieverCache用于存储监听器,变量的定义如下,它的键是 ListenerCacheKey,值是 CachedListenerRetriever
CachedListenerRetriever existingRetriever = this.retrieverCache.get(cacheKey);
if (existingRetriever == null) {
// 不存则缓存 new ListenerRetriever
if (this.beanClassLoader == null || (ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) &&
(sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {
// 初始化CachedListenerRetriever
newRetriever = new CachedListenerRetriever();
// putIfAbsent 如果传入key对应的value已经存在,就返回存在的value,不进行替换。
// 如果不存在,就添加key和value,返回null
// 此处不存在,返回null
existingRetriever = this.retrieverCache.putIfAbsent(cacheKey, newRetriever);
if (existingRetriever != null) {
newRetriever = null; // no need to populate it in retrieveApplicationListeners
}
}
}
// 此时existingRetriever 为null
if (existingRetriever != null) {
Collection<ApplicationListener<?>> result = existingRetriever.getApplicationListeners();
if (result != null) {
return result;
}
// If result is null, the existing retriever is not fully populated yet by another thread.
// Proceed like caching wasn't possible for this current local attempt.
}
return retrieveApplicationListeners(eventType, sourceType, newRetriever);
}
- event 里面的source就是SpringApplication,是在实例化ApplicationStartingEvent 时赋值的
- ListenerCacheKey 根据 event 类型和 source 类型构造出来的对象
- retrieverCache 用于存储监听器,它的键是 ListenerCacheKey,值是 CachedListenerRetriever
- existingRetriever 是已缓存的监听器
我们继续跟进 retrieveApplicationListeners 方法
private Collection<ApplicationListener<?>> retrieveApplicationListeners(
ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable CachedListenerRetriever retriever) {
List<ApplicationListener<?>> allListeners = new ArrayList<>();
Set<ApplicationListener<?>> filteredListeners = (retriever != null ? new LinkedHashSet<>() : null);
Set<String> filteredListenerBeans = (retriever != null ? new LinkedHashSet<>() : null);
Set<ApplicationListener<?>> listeners;
Set<String> listenerBeans;
synchronized (this.defaultRetriever) {
// this.defaultRetriever.applicationListeners的值是通过实例化EventPublishingRunListener时通过构造方法加入的
listeners = new LinkedHashSet<>(this.defaultRetriever.applicationListeners);
// listenerBeans是为空
listenerBeans = new LinkedHashSet<>(this.defaultRetriever.applicationListenerBeans);
}
// Add programmatically registered listeners, including ones coming
// from ApplicationListenerDetector (singleton beans and inner beans).
// 从实例化EventPublishingRunListener我们知道加入到广播器的一共有8个
for (ApplicationListener<?> listener : listeners) {
// 根据event类型source类型对listener进行匹配判断
if (supportsEvent(listener, eventType, sourceType)) {
if (retriever != null) {
filteredListeners.add(listener);
}
// 匹配上了就加入列表
allListeners.add(listener);
}
}
// 最终allListeners结果是3个:BackgroundPreinitializer、DelegatingApplicationListener、LoggingApplicationListener
// Add listeners by bean name, potentially overlapping with programmatically
// registered listeners above - but here potentially with additional metadata.
// listenerBeans为空
if (!listenerBeans.isEmpty()) {
ConfigurableBeanFactory beanFactory = getBeanFactory();
for (String listenerBeanName : listenerBeans) {
try {
if (supportsEvent(beanFactory, listenerBeanName, eventType)) {
ApplicationListener<?> listener = beanFactory.getBean(listenerBeanName, ApplicationListener.class);
if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {
if (retriever != null) {
if (beanFactory.isSingleton(listenerBeanName)) {
filteredListeners.add(listener);
} else {
filteredListenerBeans.add(listenerBeanName);
}
}
allListeners.add(listener);
}
} else {
// Remove non-matching listeners that originally came from
// ApplicationListenerDetector, possibly ruled out by additional
// BeanDefinition metadata (e.g. factory method generics) above.
Object listener = beanFactory.getSingleton(listenerBeanName);
if (retriever != null) {
filteredListeners.remove(listener);
}
allListeners.remove(listener);
}
} catch (NoSuchBeanDefinitionException ex) {
// Singleton listener instance (without backing bean definition) disappeared -
// probably in the middle of the destruction phase
}
}
}
// 匹配后的监听器排序
AnnotationAwareOrderComparator.sort(allListeners);
// retriever此时有ApplicationStartingEvent
if (retriever != null) {
if (filteredListenerBeans.isEmpty()) {
// 把匹配的监听器存储下来(为3个)
retriever.applicationListeners = new LinkedHashSet<>(allListeners);
retriever.applicationListenerBeans = filteredListenerBeans;
} else {
retriever.applicationListeners = filteredListeners;
retriever.applicationListenerBeans = filteredListenerBeans;
}
}
// 返回结果
return allListeners;
}
方法是挺长的,但是调试下来的逻辑也比较清晰,一个比较关键地方是
listeners = new LinkedHashSet<>(this.defaultRetriever.applicationListeners);
这里的 this.defaultRetriever.applicationListeners 的值是通过实例化 EventPublishingRunListener 对象时的构造方法加入的,因为比较关键我们再次提一下
private final SimpleApplicationEventMulticaster initialMulticaster;
public EventPublishingRunListener(SpringApplication application, String[] args) {
this.application = application;
this.args = args;
this.initialMulticaster = new SimpleApplicationEventMulticaster();
for (ApplicationListener<?> listener : application.getListeners()) {
//把监听器加入到广播器中,一共8个
this.initialMulticaster.addApplicationListener(listener);
}
}
方法所在类的具体路径:org.springframework.context.event.AbstractApplicationEventMulticaster,有一个添加监听器的方法: addApplicationListener
public abstract class AbstractApplicationEventMulticaster
implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware {
@Override
public void addApplicationListener(ApplicationListener<?> listener) {
synchronized (this.defaultRetriever) {
// Explicitly remove target for a proxy, if registered already,
// in order to avoid double invocations of the same listener.
Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
if (singletonTarget instanceof ApplicationListener) {
this.defaultRetriever.applicationListeners.remove(singletonTarget);
}
//此处加入的
this.defaultRetriever.applicationListeners.add(listener);
this.retrieverCache.clear();
}
}
}
另外这个8个监听器需要进行过滤,只有 event 类型和 source 类型匹配的才符合,最终是三个匹配:
- BackgroundPreinitializer
- DelegatingApplicationListener
- LoggingApplicationListener
5.6、事件匹配
那么这三个是怎么匹配的呢?通过 supportsEvent 方法实现的。
protected boolean supportsEvent(
ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) {
// 判断监听器是否是GenericApplicationListener 的一个实例
// 是,转为GenericApplicationListener 实例
// 不是,通过适配器GenericApplicationListenerAdapter来处理
GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?
(GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener));
// 只有event类型和source类型都匹配才返回true
return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));
}
- 判断监听器是否是GenericApplicationListener 的一个实例
- 是,转为GenericApplicationListener 实例,不是,通过适配器GenericApplicationListenerAdapter来处理
- 对event类型和source类型分别进行匹配判断
先看一个ApplicationStartingEvent的类图
监听器 | 对应的事件 |
---|---|
AnsiOutputApplicationListener | ApplicationEnvironmentPreparedEvent |
BackgroundPreinitializer | SpringApplicationEvent |
ClearCachesApplicationListener | ContextRefreshedEvent |
DelegatingApplicationListener | ApplicationEvent |
EnvironmentPostProcessorApplicationListener | ApplicationEnvironmentPreparedEvent、ApplicationPreparedEvent、ApplicationFailedEvent |
FileEncodingApplicationListener | ApplicationEnvironmentPreparedEvent |
LoggingApplicationListener | ApplicationStartingEvent、ApplicationEnvironmentPreparedEvent、ApplicationPreparedEvent、 ContextClosedEvent、ApplicationFailedEvent |
ParentContextCloserApplicationListener | ParentContextAvailableEvent |
其中ApplicationContextInitializedEvent、ApplicationStartingEvent、ApplicationEnvironmentPreparedEvent、ApplicationPreparedEvent、 ApplicationReadyEvent、ApplicationStartedEvent、ApplicationFailedEvent 这7个是继承SpringApplicationEvent,而 SpringApplicationEvent 继承 ApplicationEvent,属性源都是SpringApplication时,满足自身事件或父类的都会匹配上。
结合这8个监听器的对应的事件,我们可以知道满足 ApplicationStartingEvent 的就只有上面标红的三个监听器。具体匹配判断也是根据这些来的,大家可以debug看下,我就不一个个调试显示了。
5.7、监听器执行
方法所在类的具体路径:org.springframework.context.event.SimpleApplicationEventMulticaster
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
// 使用给定的事件调用给定的监听器
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
// ErrorHandler 默认为null
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
doInvokeListener(listener, event);
} catch (Throwable err) {
errorHandler.handleError(err);
}
} else {
// 调用
doInvokeListener(listener, event);
}
}
@SuppressWarnings({"rawtypes", "unchecked"})
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
// 调用监听器的onApplicationEvent方法
listener.onApplicationEvent(event);
} catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || matchesClassCastMessage(msg, event.getClass()) ||
(event instanceof PayloadApplicationEvent &&
matchesClassCastMessage(msg, ((PayloadApplicationEvent) event).getPayload().getClass()))) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
// -> let's suppress the exception.
Log loggerToUse = this.lazyLogger;
if (loggerToUse == null) {
loggerToUse = LogFactory.getLog(getClass());
this.lazyLogger = loggerToUse;
}
if (loggerToUse.isTraceEnabled()) {
loggerToUse.trace("Non-matching event type for listener: " + listener, ex);
}
} else {
throw ex;
}
}
}
}
- 遍历监听器列表,执行 invokeListener(listener, event)
- doInvokeListener(listener, event)
- 调用监听器的onApplicationEvent(event)方法
我们在上一小节就说到了只有3个符合条件的监听器,它们都会执行它们的 onApplicationEvent ,不过这三个监听器只有LoggingApplicationListener干了点事,其他两个相当于啥也没有干,大家也可以调试看下,后面会单用一篇文章解读LoggingApplicationListener。
结语
本文解读了最新版springboot监听器解析的源码,SpringApplicationRunListeners的starting也是很重要的一个流程,后续environmentPrepared、prepareContext,contextLoaded,started,ready都是一样的流程,所以大家一定要掌握,对你了解SpringBoot启动流程有很大的帮助。