SpringBoot源码学习(二) 发布启动事件
运行Spring应用程序
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
// 配置无头属性, 设置该应用程序即使没有检测到显示器也允许启动
configureHeadlessProperty();
// 从`META-INF/spring.factories`文件集中获取SpringApplicationRunListener的子类listener
SpringApplicationRunListeners listeners = getRunListeners(args);
// 开启事件监听,通知监听者们(listener)执行相应操作
listeners.starting();
try {
// 封装命令行参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 准备环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
// 配置忽略信息
configureIgnoreBeanInfo(environment);
// 打印banner
Banner printedBanner = printBanner(environment);
// 创建应用上下文
context = createApplicationContext();
// 从`META-INF/spring.factories`文件集中获取SpringBootExceptionReporter的子类
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
// 准备上下文
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
// 刷新上下
refreshContext(context);
// 刷新上下文后置处理
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
获取监听器
调用getRunListeners(args)
方法,实例化一个SpringApplicationRunListeners
对象。 通过getSpringFactoriesInstances
方法读取META-INF/spring.factories
进而实例化EventPublishingRunListener
。
/**
* 从`META-INF/spring.factories`文件集中获取SpringApplicationRunListener的子类listener
* @param args 命令行参数
* @return
*/
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
// 实例化观察模式的目标类, 在实例化时绑定监听器(SpringApplicationRunListener子类)
return new SpringApplicationRunListeners(logger,
getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
}
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener
注意: getSpringFactoriesInstances参数中的this,此方法将SpringApplication本身也传递过去了。
EventPublishingRunListener初始化
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,
ClassLoader classLoader, Object[] args, Set<String> names) {
List<T> instances = new ArrayList<>(names.size());
// 此时`names`只有`org.springframework.boot.context.event.EventPublishingRunListener`一个元素
for (String name : names) {
try {
Class<?> instanceClass = ClassUtils.forName(name, classLoader);
Assert.isAssignable(type, instanceClass);
// 行参parameterTypes此时为`new Class<?>[] { SpringApplication.class, String[].class }`
Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
// 实参此时为 `this, args`,this为SpringApplication实例, args为命令行参数
T instance = (T) BeanUtils.instantiateClass(constructor, args);
instances.add(instance);
}
catch (Throwable ex) {
throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);
}
}
return instances;
}
调用getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args)
通过反射实例化EventPublishingRunListener
。
EventPublishingRunListener实例化
public EventPublishingRunListener(SpringApplication application, String[] args) {
this.application = application;
// 命令行参数
this.args = args;
// 事件多播器
this.initialMulticaster = new SimpleApplicationEventMulticaster();
/**
* org.springframework.boot.devtools.restart.RestartApplicationListener,
* org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,
* org.springframework.boot.context.config.ConfigFileApplicationListener,
* org.springframework.boot.context.config.AnsiOutputApplicationListener,
* org.springframework.boot.context.logging.LoggingApplicationListener,
* org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,
* org.springframework.boot.autoconfigure.BackgroundPreinitializer,
* org.springframework.boot.context.config.DelegatingApplicationListener,
* org.springframework.boot.builder.ParentContextCloserApplicationListener,
* org.springframework.boot.devtools.logger.DevToolsLogFactory$Listener,
* org.springframework.boot.ClearCachesApplicationListener,
* org.springframework.boot.context.FileEncodingApplicationListener,
* org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
*/
for (ApplicationListener<?> listener : application.getListeners()) {
this.initialMulticaster.addApplicationListener(listener);
}
}
依赖关系图谱
SimpleApplicationEventMulticaster实例化
此源码为AbstractApplicationEventMulticaster中方法。
@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();
}
}
启动监听器
listeners.starting();
void starting() {
// org.springframework.boot.context.event.EventPublishingRunListener
for (SpringApplicationRunListener listener : this.listeners) {
listener.starting();
}
}
调用EventPublishingRunListener
中的starting()
方法。
@Override
public void starting() {
// 构造EventObject事件, source为application并广播事件,通知各个监听器
this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
}
广播Event
@Override
public void multicastEvent(ApplicationEvent event) {
// 过滤监听器,为其广播事件。resolveDefaultEventType(event)除了`org.springframework.http.client.PublisherEntity`和`org.springframework.context.PayloadApplicationEvent`其余返回new ResolvableType(clazz)
multicastEvent(event, resolveDefaultEventType(event));
}
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
/**
* 返回与给定事件类型匹配的ApplicationListeners的集合。不匹配的监听器会被排除在外。
* org.springframework.boot.devtools.restart.RestartApplicationListener,
* org.springframework.boot.context.logging.LoggingApplicationListener,
* org.springframework.boot.autoconfigure.BackgroundPreinitializer,
* org.springframework.boot.context.config.DelegatingApplicationListener,
* org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
*/
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
// 用给定的事件调用给定的监听器。
invokeListener(listener, event);
}
}
}
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
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 {
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
// -> let's suppress the exception and just log a debug message.
Log logger = LogFactory.getLog(getClass());
if (logger.isTraceEnabled()) {
logger.trace("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}