1. 介绍
Spring有两大类事件 ,一类是 Application事件,超类是SpringApplicationEvent, 这类事件是在Spring程序启动时,每执行到一个阶段就发出一个事件,依次对应ApplicationStartingEvent到ApplicationReadyEvent,表示spring程序从启动开始到启动完成的过程。当然还有一个如果在启动过程中出现异常,就会发出 ApplicationFailedEvent 事件。
另一类是ApplicationContext事件,超类是 ApplicationContextEvent ,这类事件 表示ApplicationContext生命周期内的各个阶段 。
2. 内置事件
其中spring有一些内置的事件,当完成某种操作时会发出某些事件动作。
ApplicationContext内置事件
序号 | 内置事件 | 描述 |
1 | ContextRefreshedEvent | ApplicationContext 被初始化或刷新时,该事件被发布。这也可以在 ConfigurableApplicationContext接口中使用 refresh() 方法来发生。此处的初始化是指:所有的Bean被成功装载后处理Bean被检测并激活,所有Singleton Bean 被预实例化,ApplicationContext容器已就绪可用 |
2 | ContextStartedEvent | 当使用 ConfigurableApplicationContext (ApplicationContext子接口)接口中的 start() 方法启动 ApplicationContext 时,该事件被发布。你可以调查你的数据库,或者你可以在接受到这个事件后重启任何停止的应用程序。 |
3 | ContextStoppedEvent | 当使用 ConfigurableApplicationContext 接口中的 stop() 停止 ApplicationContext 时,发布这个事件。你可以在接受到这个事件后做必要的清理的工作。 |
4 | ContextClosedEvent | 当使用 ConfigurableApplicationContext 接口中的 close() 方法关闭 ApplicationContext 时,该事件被发布。一个已关闭的上下文到达生命周期末端;它不能被刷新或重启 |
SpringApplicationEvent内置事件:
前5种事件,是Spring按照启动前后顺序,依次生成的。我们想要监听启动之前的事件和启动完成的事件,只需关注ApplicationStartingEvent和ApplicationReadyEvent
序号 | 内置事件 | 描述 |
1 | ApplicationStartingEvent |
除了基础的注册监听和初始化之外,在开始运行时做任何处理动作之前发送 。 |
2 | ApplicationEnvironmentPreparedEvent |
在上下文中使用的环境已知,但是Context尚未创建之前发送 |
3 | ApplicationPreparedEvent |
在Spring刷新Context开始之前,而仅当加载bean定义之后发送 |
4 | ApplicationStartedEvent |
在刷新上下文之后,但在调用任何应用程序(ApplicationRunner)和命令行运行程序(CommandLineRunner)之前发送 |
5 | ApplicationReadyEvent |
在调用应用程序和命令行运行程序后发送。 它表示应用程序已准备好为请求提供服务。 |
6 | ApplicationFailedEvent |
在启动过程中出现异常时发送。 |
RequestHandledEvent内置事件:这是一个特定web事件,告诉所有 bean HTTP 请求已经被服务。只能应用于使用DispatcherServlet的Web应用。在使用Spring作为前端的MVC控制器时,当Spring处理用户请求结束后,系统会自动触发该事件。
序号 | 内置事件 | 描述 |
1 | ServletRequestHandledEvent | 包含特定请求上下文的信息 |
ApplicationEvent继承关系
3. 内置事件的使用和执行时机
内置事件的执行官方提供了两种方式
第一种:通过SPI扩展方式 META-INF/spring.factories中添加配置ApplicationListener
# Initializer
org.springframework.context.ApplicationContextInitializer=\
com.example.demo.initializer.TestApplicationContextInitializer
# Application Listeners
org.springframework.context.ApplicationListener=\
com.example.demo.listener.TestApplicationListener
TestApplicationListener 类实现接口ApplicationListener,泛型参数为ApplicationEvent时则监听所有类型的内置事件。如果要监听指定类型的内置事件,可转入指定Event类即可,如:要监听ApplicationContext刷新事件则可以只监听ContextRefreshedEvent。
public class TestApplicationListener implements ApplicationListener<ApplicationEvent>{
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("执行ApplicationEvent事件:"+event.getClass().getSimpleName());
}
}
执行结果:可以看到每种事件发出的时机和顺序
执行ApplicationEvent事件:ApplicationStartingEvent
执行ApplicationEvent事件:ApplicationEnvironmentPreparedEvent
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.2.5.RELEASE)
Initializer调用:
执行ApplicationEvent事件:ApplicationContextInitializedEvent
2020-03-19 09:40:42.694 INFO 93896 --- [ main] com.example.demo.DemoApplication : Starting DemoApplication on ZZ-WZ112019 with PID 93896 (E:\java_work\demo\target\classes started by jiafeng in E:\java_work\demo)
2020-03-19 09:40:42.696 INFO 93896 --- [ main] com.example.demo.DemoApplication : No active profile set, falling back to default profiles: default
执行ApplicationEvent事件:ApplicationPreparedEvent
执行ApplicationEvent事件:ContextRefreshedEvent
2020-03-19 09:40:42.978 INFO 93896 --- [ main] com.example.demo.DemoApplication : Started DemoApplication in 0.525 seconds (JVM running for 0.834)
执行ApplicationEvent事件:ApplicationStartedEvent
执行ApplicationEvent事件:ApplicationReadyEvent
启动完成
执行ApplicationEvent事件:ContextClosedEvent
第二种:在启动类里面 添加监听器
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
//SpringApplication.run(DemoApplication.class, args);
SpringApplication application = new SpringApplication(DemoApplication.class);
application.addListeners(new TestApplicationListener()); //添加监听器
application.run(args);
System.out.println("启动完成");
}
}
或者SpringApplicationBuilder类添加监听器
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
//SpringApplication.run(DemoApplication.class, args);
// SpringApplication application = new SpringApplication(DemoApplication.class);
// application.addListeners(new TestApplicationListener()); //添加监听器
// application.run(args);
new SpringApplicationBuilder(DemoApplication.class)
.listeners(new TestApplicationListener()) //添加监听器
.run(args);
System.out.println("启动完成");
}
}
执行结果:跟SIP方式执行结果相同
执行ApplicationEvent事件:ApplicationStartingEvent
执行ApplicationEvent事件:ApplicationEnvironmentPreparedEvent
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.2.5.RELEASE)
Initializer调用:
执行ApplicationEvent事件:ApplicationContextInitializedEvent
2020-03-19 10:00:24.874 INFO 99744 --- [ main] com.example.demo.DemoApplication : Starting DemoApplication on ZZ-WZ112019 with PID 99744 (E:\java_work\demo\target\classes started by jiafeng in E:\java_work\demo)
2020-03-19 10:00:24.875 INFO 99744 --- [ main] com.example.demo.DemoApplication : No active profile set, falling back to default profiles: default
执行ApplicationEvent事件:ApplicationPreparedEvent
执行ApplicationEvent事件:ContextRefreshedEvent
2020-03-19 10:00:25.153 INFO 99744 --- [ main] com.example.demo.DemoApplication : Started DemoApplication in 0.515 seconds (JVM running for 0.829)
执行ApplicationEvent事件:ApplicationStartedEvent
执行ApplicationEvent事件:ApplicationReadyEvent
启动完成
执行ApplicationEvent事件:ContextClosedEvent
来源:oschina
链接:https://my.oschina.net/u/3100849/blog/3198030