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); } } |
读取监听配置并进行实例化:
SpringApplicationRunListeners类主要是将一组SpringApplicationRunListener聚合到一起,然后使用统一的方式传播事件。
其实现逻辑如下,主要就是将事件传播到各个SpringApplicationRunListener实例。
EventPublishingRunListener是springboot的默认事件监听器,源码如下:
具体的事件传播过程如下:
遍历所有ApplicationListener,并从线程池中获取空闲线程进行回调。
上述几个监听器类关系如下图所示:
一般在系统中,如果需要监听springboot的生命周期,比如在启动完成后需要进行相关数据初始化,更好的办法是实现ApplicationListener监听器,而不是SpringApplicationRunListener监听器。
ApplicationListener监听编程实例:
假设我需要在系统启动时,执行某些操作,代码如下:
更一般的实例:
假设在用户注册成功后,需要向用户发送短信、邮件、积分等信息时,也可以使用springboot的事件监听,代码如下: