SpringApplicationRunListener 接口的作用主要就是在Spring Boot 启动初始化的过程中可以通过SpringApplicationRunListener接口回调来让用户在启动的各个流程中可以加入自己的逻辑。
Spring Boot启动过程的关键事件(按照触发顺序)包括:
- 开始启动
- Environment构建完成
- ApplicationContext构建完成
- ApplicationContext完成加载
- ApplicationContext完成刷新并启动
- 启动完成
- 启动失败
接口定义
下面是SpringApplicationRunListener接口定义:
package org.springframework.boot;
public interface SpringApplicationRunListener {
// 在run()方法开始执行时,该方法就立即被调用,可用于在初始化最早期时做一些工作
void starting();
// 当environment构建完成,ApplicationContext创建之前,该方法被调用
void environmentPrepared(ConfigurableEnvironment environment);
// 当ApplicationContext构建完成时,该方法被调用
void contextPrepared(ConfigurableApplicationContext context);
// 在ApplicationContext完成加载,但没有被刷新前,该方法被调用
void contextLoaded(ConfigurableApplicationContext context);
// 在ApplicationContext刷新并启动后,CommandLineRunners和ApplicationRunner未被调用前,该方法被调用
void started(ConfigurableApplicationContext context);
// 在run()方法执行完成前该方法被调用
void running(ConfigurableApplicationContext context);
// 当应用运行出错时该方法被调用
void failed(ConfigurableApplicationContext context, Throwable exception);
}
自定义SpringApplicationRunListener
我们可以通过实现自定义SpringApplicationRunListener来监听Spring Boot的启动流程,并在各个回调方法中处理自己的逻辑。
实现自定义SpringApplicationRunListener需要实现SpringApplicationRunListener接口,并且必须提供一个包含参数(SpringApplication application, String[] args)的构造方法,如下所示:
public class HelloApplicationRunListener implements SpringApplicationRunListener {
public HelloApplicationRunListener(SpringApplication application, String[] args){
System.out.println("constructor");
}
@Override
public void starting() {
System.out.println("starting...");
}
@Override
public void environmentPrepared(ConfigurableEnvironment environment) {
System.out.println("environmentPrepared...");
}
@Override
public void contextPrepared(ConfigurableApplicationContext context) {
System.out.println("contextPrepared...");
}
@Override
public void contextLoaded(ConfigurableApplicationContext context) {
System.out.println("contextLoaded...");
}
@Override
public void started(ConfigurableApplicationContext context) {
System.out.println("started...");
}
@Override
public void running(ConfigurableApplicationContext context) {
System.out.println("running...");
}
@Override
public void failed(ConfigurableApplicationContext context, Throwable exception) {
System.out.println("failed...");
}
}
在spring.factories中配置自定义SpringApplicationRunListener,之后在启动Spring Boot应用时,就会自动将HelloApplicationRunListener实例化,并在Spring容器初始化的各个阶段回调对应的方法。
如果想知道为什么必须在spring.factories中配置,可以参考我的另一篇文章Spring Factories
org.springframework.boot.SpringApplicationRunListener=\
com.yidian.data.listener.HelloApplicationRunListener
启动应用程序,输出结果如下:
constructor
starting...
constructor
starting...
environmentPrepared...
contextPrepared...
contextLoaded...
started...
running...
environmentPrepared...
Spring事件触发过程
Spring的事件触发过程是交由SpringApplicationRunListener接口的实现类EventPublishingRunListener来代理实现的。
EventPublishingRunListener的构造方法如下:
public EventPublishingRunListener(SpringApplication application, String[] args) {
this.application = application;
this.args = args;
this.initialMulticaster = new SimpleApplicationEventMulticaster();
for (ApplicationListener> listener : application.getListeners()) {
this.initialMulticaster.addApplicationListener(listener);
}
}
EventPublishingRunListener包含三个成员变量:
- application:当前运行的SpringApplication实例
- args:启动命令行参数
- initialMulticaster:事件广播器
在构造EventPublishingRunListener实例的过程中,会将application关联的所有ApplicationListener实例关联到initialMulticaster中,以方便initialMulticaster将事件传递给所有的监听器。
- 当对应的时间处理方法被调用时,EventPublishingRunListener会将application和args封装到对应的SpringApplicationEvent子类实例中;
- initialMulticaster会根据事件类型和触发源对事件进行分类,并与对应的ApplicationListener建立关联关系,之后将事件传递给对应的ApplicationListener;
- ApplicationListener实例收到事件后,会根据时间类型不同,执行不同的处理逻辑。
SpringApplicationEvent的继承关系如下图,每一个子类都对应Spring Boot启动过程中的一个关键事件。