SpringApplicationRunListener

SpringApplicationRunListener 接口的作用主要就是在Spring Boot 启动初始化的过程中可以通过SpringApplicationRunListener接口回调来让用户在启动的各个流程中可以加入自己的逻辑。
Spring Boot启动过程的关键事件(按照触发顺序)包括:

  1. 开始启动
  2. Environment构建完成
  3. ApplicationContext构建完成
  4. ApplicationContext完成加载
  5. ApplicationContext完成刷新并启动
  6. 启动完成
  7. 启动失败

接口定义

下面是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包含三个成员变量:

  1. application:当前运行的SpringApplication实例
  2. args:启动命令行参数
  3. initialMulticaster:事件广播器

在构造EventPublishingRunListener实例的过程中,会将application关联的所有ApplicationListener实例关联到initialMulticaster中,以方便initialMulticaster将事件传递给所有的监听器。

  1. 当对应的时间处理方法被调用时,EventPublishingRunListener会将application和args封装到对应的SpringApplicationEvent子类实例中;
  2. initialMulticaster会根据事件类型和触发源对事件进行分类,并与对应的ApplicationListener建立关联关系,之后将事件传递给对应的ApplicationListener;
  3. ApplicationListener实例收到事件后,会根据时间类型不同,执行不同的处理逻辑。

SpringApplicationEvent的继承关系如下图,每一个子类都对应Spring Boot启动过程中的一个关键事件。

你可能感兴趣的:(SpringApplicationRunListener)