SpringBoot之Application Events、Li
一、前言
在SpringBoot启动的过程中会产生一系列事件,我们开发的时候可以自定义一些事件监听处理器。根据自己的需要在针对每个事件做一些业务处理。
二、Application Events
SpringBoot 启动的时候会按顺序产生如下几种事件:
-
ApplicationStartingEvent
:SpringBoot应用启动且未作任何处理(除listener注册和初始化)的时候发送ApplicationStartingEvent
。 -
ApplicationEnvironmentPreparedEvent
:确定SpringBoot应用使用的Environment且context创建之前发送这个事件。 -
ApplicationPreparedEvent
:context已经创建且没有refresh发送个事件。 -
ApplicationStartedEvent
:context已经refresh且application and command-line runners(如果有) 调用之前发送这个事件。 -
ApplicationReadyEvent
:application and command-line runners (如果有)执行完后发送这个事件,此时应用已经启动完毕,这个事件比较常用,常常在系统启动完后做一些初始化操作。 -
ApplicationFailedEvent
:应用启动失败后产生这个事件。
三、使用场景
3.1 场景说明
SpringBoot应用启动后自动调用接口(或组件),做一些初始化操作。
3.2 需要初始化操作的接口
首先模拟系统启动后需要进行业务操作,这里只是范例,所以只打印一句话:
import org.springframework.stereotype.Component;
@Component
public class SystemInitService {
public void systemInit() {
System.out.println("调用SystemInitService,应用初始化后,进行一些业务操作,如启动某些工作线程,初始化系统某些参数");
}
}
3.3 事件监听处理实现
通过实现ApplicationListener接口,完成事件的监听处理:
import org.springframework.boot.context.event.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
public class MyApplicationListener implements ApplicationListener<ApplicationEvent> {
@Override
public void onApplicationEvent(ApplicationEvent event) {
//SpringBoot应用启动且未作任何处理(除listener注册和初始化)的时候发送ApplicationStartingEvent
if (event instanceof ApplicationStartingEvent) {
System.out.println("执行:ApplicationStarting");
return;
}
//确定springboot应用使用的Environment且context创建之前发送这个事件
if (event instanceof ApplicationEnvironmentPreparedEvent) {
System.out.println("执行:ApplicationEnvironmentPrepared");
return;
}
//context已经创建且没有refresh发送个事件
if (event instanceof ApplicationPreparedEvent) {
System.out.println("执行:ApplicationPrepared");
return;
}
//context已经refresh且application and command-line runners(如果有) 调用之前发送这个事件
if (event instanceof ApplicationStartedEvent) {
System.out.println("执行:ApplicationStarted");
return;
}
//application and command-line runners (如果有)执行完后发送这个事件,此时应用已经启动完毕
if (event instanceof ApplicationReadyEvent) {
ApplicationContext context = ((ApplicationReadyEvent) event).getApplicationContext();
SystemInitService initService = context.getBean(SystemInitService.class);
initService.systemInit();
return;
}
//应用启动失败后产生这个事件
if (event instanceof ApplicationFailedEvent) {
System.out.println("执行:ApplicationFailed");
return;
}
}
}
3.4 监听器Listener注册
3.4.1 方式一
第一种方式是手动注册,即在SpringApplication初始化的时候添加进去
import com.alanchen.demo.service.MyApplicationListener;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
@SpringBootApplication
public class SpringbootTestApplication {
public static void main(String[] args) {
//SpringApplication.run(SpringbootTestApplication.class, args);
new SpringApplicationBuilder().sources(SpringbootTestApplication.class)
.listeners(new MyApplicationListener()).run(args);
}
}
3.4.2 方式二
第二种方式是,自动注册(SpringBoot本身Listener实现也是通过这种方式)。在resources目录下添加META-INF
目录,然后在META-INF目录里添加spring.factories
文件,文件内容是:
org.springframework.context.ApplicationListener=\
com.alanchen.demo.service.MyApplicationListener
通过自动注册的方式main入口就与无listener时一样:
import com.alanchen.demo.service.MyApplicationListener;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
@SpringBootApplication
public class SpringbootTestApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootTestApplication.class, args);
//new SpringApplicationBuilder().sources(SpringbootTestApplication.class).listeners(new MyApplicationListener()).run(args);
}
}
3.5 服务启动日志
启动后控制台打印如下
执行:ApplicationStarting
执行:ApplicationEnvironmentPrepared
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.6.4)
2022-03-18 15:06:04.349 INFO 18040 --- [ main] c.a.demo.SpringbootTestApplication : Starting SpringbootTestApplication using Java 1.8.0_131 on LAPTOP-R0R80SCR with PID 18040 (E:\code\springboot-test\target\classes started by kwb in E:\code\springboot-test)
2022-03-18 15:06:04.352 INFO 18040 --- [ main] c.a.demo.SpringbootTestApplication : No active profile set, falling back to 1 default profile: "default"
执行:ApplicationPrepared
2022-03-18 15:06:04.925 INFO 18040 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2022-03-18 15:06:04.929 INFO 18040 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2022-03-18 15:06:04.929 INFO 18040 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.58]
2022-03-18 15:06:04.980 INFO 18040 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2022-03-18 15:06:04.980 INFO 18040 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 599 ms
2022-03-18 15:06:05.157 INFO 18040 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2022-03-18 15:06:05.162 INFO 18040 --- [ main] c.a.demo.SpringbootTestApplication : Started SpringbootTestApplication in 1.032 seconds (JVM running for 1.583)
执行:ApplicationStarted
调用SystemInitService,应用初始化后,进行一些业务操作,如启动某些工作线程,初始化系统某些参数