23.5应用程序事件和监听器
除了通常的Spring框架事件之外,例如 ContextRefreshedEvent , SpringApplication 还会发送一些其他应用程序事件。
某些事件实际上是在创建 ApplicationContext 之前触发的,因此您无法在 @Bean 上注册侦听器。您可以使
用 SpringApplication.addListeners(… ) 方法或 SpringApplicationBuilder.listeners(… ) 方法注册它们。
如果您希望自动注册这些侦听器,无论应用程序的创建方式如何,您都可以将 META-INF/spring.factories 文件添加到项目中并
使用 org.springframework.context.ApplicationListener 键引用您的侦听器,如下所示:以下示例:
org.springframework.context.ApplicationListener=com.example.project.MyListener
应用程序运行时,应按以下顺序发送应用程序事件:
1. 除了注册侦听器和初始化程序之外,在运行开始时但在任何处理之前发送 ApplicationStartingEvent 。
2. 当在上下文中使用的 Environment 已知但在创建上下文之前,将发送 ApplicationEnvironmentPreparedEvent 。
3. 在刷新开始之前但在加载bean定义之后发送 ApplicationPreparedEvent 。
4. 在刷新上下文之后但在调用任何应用程序和命令行运行程序之前发送 ApplicationStartedEvent 。
5. 在调用任何应用程序和命令行运行程序后发送 ApplicationReadyEvent 。它表示应用程序已准备好为请求提供服务。
6. 如果启动时发生异常,则会发送 ApplicationFailedEvent 。
您经常不需要使用应用程序事件,但知道它们存在可能很方便。在内部,Spring Boot使用事件来处理各种任务。
应用程序事件使用Spring Framework的事件发布机制发送。此机制的一部分确保在子上下文中发布给侦听器的事件也会在任何祖先上下文中发
布给侦听器。因此,如果您的应用程序使用 SpringApplication 实例的层次结构,则侦听器可能会收到相同类型的应用程序事件的多个实例。
为了允许侦听器区分其上下文的事件和后代上下文的事件,它应该请求注入其应用程序上下文,然后将注入的上下文与事件的上下文进行比较。
可以通过实现 ApplicationContextAware 或者如果监听器是bean,使用 @Autowired 来注入上下文。
23.6网络环境
SpringApplication 试图代表您创建正确类型的 ApplicationContext 。用于确定 WebApplicationType 的算法非常简单:
如果存在Spring MVC,则使用 AnnotationConfigServletWebServerApplicationContext
如果Spring MVC不存在且存在Spring WebFlux,则使用 AnnotationConfigReactiveWebServerApplicationContext
否则,使用 AnnotationConfigApplicationContext
这意味着如果您在同一个应用程序中使用Spring MVC和来自Spring WebFlux的新 WebClient ,默认情况下将使用Spring MVC。您可以通过
调用 setWebApplicationType(WebApplicationType) 轻松覆盖它。
也可以通过调用 setApplicationContextClass(… ) 来完全控制使用的 ApplicationContext 类型。
在JUnit测试中使用 SpringApplication 时,通常需要调用 setWebApplicationType(WebApplicationType.NONE) 。