# 23.5. 应用事件和监听器

除了常见的Spring框架事件，比如[ContextRefreshedEvent](https://docs.spring.io/spring/docs/5.0.4.RELEASE/javadoc-api/org/springframework/context/event/ContextRefreshedEvent.html)，`SpringApplication`也会发送其他的应用事件。

**注** 有些事件实际上是在`ApplicationContext`创建前触发的，所以你不能在那些事件（处理类）中通过`@Bean`注册监听器，只能通过`SpringApplication.addListeners(…)`或`SpringApplicationBuilder.listeners(…)`方法注册。如果想让监听器自动注册，而不关心应用的创建方式，你可以在工程中添加一个`META-INF/spring.factories`文件，并使用`org.springframework.context.ApplicationListener`作为key指向那些监听器，如下：

```
org.springframework.context.ApplicationListener=com.example.project.MyListener
```

应用运行时，事件会以下面的次序发送：

1. 在运行开始，但除了监听器注册和初始化以外的任何处理之前，会发送一个`ApplicationStartingEvent`。
2. 在Environment将被用于已知的上下文，但在上下文被创建前，会发送一个`ApplicationEnvironmentPreparedEvent`。
3. 在refresh开始前，但在bean定义已被加载后，会发送一个`ApplicationPreparedEvent`。
4. 在上下文更新后，但在任何应用和命令行运行器被调用前，会发送一个`ApplicationStartedEvent`。
5. 在任何应用和命令行运行器被调用后，会发送一个`ApplicationReadyEvent`，表示应用准备好接收请求了。
6. 启动过程中如果出现异常，会发送一个`ApplicationFailedEvent`。

**注** 通常不需要使用应用事件，但知道它们的存在是有用的（在某些场合可能会使用到），比如，在Spring Boot内部会使用事件处理各种任务。

应用事件通过Spring框架的事件发布机制发送。此机制的一部分确保了一个发布到子上下文里的监听器的事件，也会发布到任何祖先上下文里的监听器。因此，如果你的应用使用`SpringApplication`实例的层级，监听器可能会接收到应用事件的多个相同类型的实例。

为了让你的监听器区分一个事件是对应它的上下文还是子孙上下文，它应当请求它的应用上下文被注入，然后比较注入的上下文与事件的上下文。上下文可以通过实现`ApplicationContextAware`注入。或者，如果监听器是一个bean，可以使用`@Autowired`。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://jack80342.gitbook.io/spring-boot/iv.-spring-boot-features/23.-springapplication/23.5.-application-events-and-listeners.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
