springboot生命周期和监听器

时间:2024-04-02 07:34:15

Spring boot应用,这里具体的来说,是指类SpringApplication,在其run()方法运行过程中,主要围绕所使用ApplicationContext对象的生命周期事件,应用了一个事件监听器机制提供了相应的程序扩展入口点,开发人员可以基于此机制,在相应的事件发生时执行特定的逻辑。

SpringApplication应用的该事件监听器机制主要利用如下两个类/接口 :

SpringApplicationRunListeners

SpringApplicationRunListener

简单来讲,在SpringApplication的run()方法执行时,应用上下文ApplicationContext对象创建之前,应用程序会首先找到配置中所定义的所有SpringApplicationRunListener的实现类(这些实现类可能由Spring boot自身实现和提供,也可以由开发人员来实现和提供),创建他们的实例,然后把它们放在一个集合中,然后封装为一个 SpringApplicationRunListeners 实例。之后Spring boot应用开始创建ApplicationContext对象,然后在相应的ApplicationContext的生命周期事件发生时,程序会通过该SpringApplicationRunListeners 实例向各个 SpringApplicationRunListener 实例广播相应的事件,从而SpringApplicationRunListener 实现类中相应的监听器逻辑得到执行。

这里所提到的SpringApplicationContext的生命周期事件,具体来讲,是如下事件 :

发生顺序 事件 事件类型 备注
1 starting ApplicationStartedEvent 系统刚启动
2 environmentPrepared ApplicationEnvironmentPreparedEvent 环境已经准备好,但是ApplicationContext实例尚未被创建
3 contextPrepared   ApplicationContext已经被创建并且准备就绪,但是sources尚未被加载
4 contextLoaded ApplicationPreparedEvent ApplicationContext实例的sources已经被加载,但是ApplicationContext实例尚未被刷新(refresh)
5 finished ApplicationFailedEvent
ApplicationReadyEvent
Spring应用程序启动完成时发送该事件,此时ApplicationContext实例已经成功创建完成,或者遇到异常创建失败。对于该ApplicationContext是一个WebApplicationContext的情况,此时内置的Web容器已经在其他线程启动处于服务就绪状态,而SpringApplication执行主线程已经完成自己的
任务。

 

SpringApplication.run()方法中事件监听有关逻辑

// SpringApplication 类
public ConfigurableApplicationContext run(String... args) {
     StopWatch stopWatch = new StopWatch();
     stopWatch.start();
     ConfigurableApplicationContext context = null;
     FailureAnalyzers analyzers = null;
     configureHeadlessProperty();
     // 从配置中获取SpringApplicationRunListener实现类并实例化,
     // 最终把所有这些实例包装到一个SpringApplicationRunListeners实例来使用
     SpringApplicationRunListeners listeners = getRunListeners(args);
     // 启动各个SpringApplicationRunListener 监听器实例 
     listeners.starting();
     try {
          ApplicationArguments applicationArguments = 
               new DefaultApplicationArguments(args);
          // 准备环境
          // 结束时会向各个SpringApplicationRunListener发送事件 
          // environmentPrepared     
          ConfigurableEnvironment environment = 
               prepareEnvironment(listeners,applicationArguments);
          Banner printedBanner = printBanner(environment);
          context = createApplicationContext();// 这里创建应用上下文
          analyzers = new FailureAnalyzers(context);
         // 准备应用上下文,
         // 完成时会向各个SpringApplicationRunListener发送事件 
         // contextPrepared
         prepareContext(context, environment, listeners, 
                applicationArguments,printedBanner);
         refreshContext(context);
         afterRefresh(context, applicationArguments);
        // 应用上下文准备完成
        // 向各个SpringApplicationRunListener发送事件 
        // finished
        listeners.finished(context, null);
        stopWatch.stop();
        if (this.logStartupInfo) {
             new StartupInfoLogger(this.mainApplicationClass)
                .logStarted(getApplicationLog(), stopWatch);
         }
         return context;
     }catch (Throwable ex) {
        // 应用上下文准备遇到异常时,
       // 向各个SpringApplicationRunListener发送事件finished,
       // 携带响应异常信息
       handleRunFailure(context, listeners, analyzers, ex);
       throw new IllegalStateException(ex);
     }
}

读取监听配置并进行实例化:

springboot生命周期和监听器

SpringApplicationRunListeners类主要是将一组SpringApplicationRunListener聚合到一起,然后使用统一的方式传播事件。

其实现逻辑如下,主要就是将事件传播到各个SpringApplicationRunListener实例。

springboot生命周期和监听器

EventPublishingRunListener是springboot的默认事件监听器,源码如下:

springboot生命周期和监听器

具体的事件传播过程如下:

springboot生命周期和监听器

遍历所有ApplicationListener,并从线程池中获取空闲线程进行回调。

上述几个监听器类关系如下图所示:

springboot生命周期和监听器

一般在系统中,如果需要监听springboot的生命周期,比如在启动完成后需要进行相关数据初始化,更好的办法是实现ApplicationListener监听器,而不是SpringApplicationRunListener监听器。

ApplicationListener监听编程实例:

假设我需要在系统启动时,执行某些操作,代码如下:

springboot生命周期和监听器

更一般的实例:

假设在用户注册成功后,需要向用户发送短信、邮件、积分等信息时,也可以使用springboot的事件监听,代码如下:

springboot生命周期和监听器