Spring Framework版本:5.1.6.RELEASE (点击跳转官方文档)
SpringBoot版本:2.1.4.RELEASE (点击跳转官方文档)
Event handling in the ApplicationContext is provided through the ApplicationEvent class and the ApplicationListener interface. If a bean that implements the ApplicationListener interface is deployed into the context, every time an ApplicationEvent gets published to the ApplicationContext, that bean is notified. Essentially, this is the standard Observer design pattern.
ApplicationContext 通过 ApplicationEvent 类和 ApplicationListener 接口进行事件处理。 如果将实现 ApplicationListener 接口的 Bean 注入到上下文中,则每次使用 ApplicationContext 发布 ApplicationEvent 时,都会通知该 Bean。 本质上,这是标准的观察者设计模式,是事件驱动模型在设计层面的体现。
1. 概览
以下是 SpringBoot 启动过程中相关的事件类型(按序):
事件 | 所属 | 说明 |
---|---|---|
ApplicationStartingEvent | Spring Boot | 应用程序启动,ApplicationContext(容器) 创建之前触发的事件 |
ApplicationEnvironmentPreparedEvent | Spring Boot | 容器环境准备已完成,容器创建之前触发的事件 |
ApplicationContextInitializedEvent | Spring Boot | 容器已创建,容器中所有 ApplicationContextInitializer 实现类的 initialize 方法调用结束后触发的事件 |
ApplicationPreparedEvent | Spring Boot | 容器已创建,还没有被刷新,但已准备完毕。 |
ContextRefreshedEvent | Spring Framework | 容器已经刷新并准备好使用。 |
ServletWebServerInitializedEvent | Spring Boot | |
ApplicationStartedEvent | Spring Boot | 在容器刷新后,并且还没有调用任何程序或命令行程序时发布的事件。 |
ApplicationReadyEvent | Spring Boot | 在容器/服务已经准备好提供请求时发布的事件。 |
ApplicationFailedEvent | Spring Boot | 在容器启动出错时发布的事件。 |
值得注意的是,有些事件是在 ApplicationContext 创建之前触发的,因此不能使用注解进行声明。
Some events are actually triggered before the
ApplicationContext
is created, so you cannot register a listener on those as a@Bean
. You can register them with theSpringApplication.addListeners(…)
method or theSpringApplicationBuilder.listeners(…)
method.If you want those listeners to be registered automatically, regardless of the way the application is created, you can add a
META-INF/spring.factories
file to your project and reference your listener(s) by using theorg.springframework.context.ApplicationListener
key, as shown in the following example:
org.springframework.context.ApplicationListener=com.example.project.MyListener
以下是部分事件被执行的时机及各自的顺序:
2. ApplicationStartingEvent
ApplicationStartingEvent 在容器刚启动,ApplicationContext 创建之前触发的事件。不能使用注解进行声明。
1 | public class ApplicationStartingEventListenerExample implements ApplicationListener<ApplicationStartingEvent> { |
源码中被调用的位置:org.springframework.boot.SpringApplication#run(java.lang.String...)
。
3. ApplicationEnvironmentPreparedEvent
ApplicationEnvironmentPreparedEvent 在容器启动后,并且环境信息可用于检查和修改时发布的事件。不能使用注解进行声明。
1 | public class ApplicationEnvironmentPreparedEventListenerExample implements ApplicationListener<ApplicationEnvironmentPreparedEvent> { |
源码中被调用的位置:org.springframework.boot.SpringApplication#prepareEnvironment
。
4. ApplicationContextInitializedEvent
ApplicationContextInitializedEvent 在容器初始化时发布的事件。不能使用注解进行声明。
1 | public class ApplicationContextInitializedEventListenerExample implements ApplicationListener<ApplicationContextInitializedEvent> { |
源码中被调用的位置:org.springframework.boot.SpringApplication#prepareContext
。
5. ApplicationPreparedEvent
ApplicationPreparedEvent 在容器准备就绪时发布的事件。可以使用注解进行声明。
1 |
|
源码中被调用的位置:org.springframework.boot.SpringApplication#prepareContext
。
使用 @EventListener
注解方式:
1 |
|
6. ApplicationStartedEvent
ApplicationStartedEvent 在容器刷新后,并且还没有调用任何程序或命令行程序时发布的事件。可以使用注解进行声明。
1 |
|
源码中被调用的位置:org.springframework.boot.SpringApplication#run(java.lang.String...)
。
使用 @EventListener
注解方式
1 |
|
7. ApplicationReadyEvent
ApplicationReadyEvent 在 容器/服务 已经准备好提供请求时发布的事件,可以使用注解进行声明。
1 |
|
源码中被调用的位置:org.springframework.boot.SpringApplication#run(java.lang.String...)
。
使用 @EventListener
注解方式
1 |
|
8. ApplicationFailedEvent
忽略
9. 使用 spel 表达式
@EventListener
中的 condition
属性可以指定 SpEL 表达式条件,只有当事件内容是 update 时才监听器方法才处理该事件。
1 |
|
10. 示例代码
启动类示例代码
1 |
|
11. Reference
- spring core context-functionality-events
- Application Events and Listeners
- 不懂SpringApplication生命周期事件?那就等于不会Spring Boot嘛
- Spring Events 介绍和实现