除了常见的 Spring 框架事件,比如 ContextRefreshedEvent,SpringApplication 也会发送其他的 application 事件。
有些事件实际上是在 ApplicationContext 创建前触发的,所以你不能在那些事件(处理类)中通过 @Bean 注册监听器,只能通过 SpringApplication.addListeners(…) 或 SpringApplicationBuilder.lis teners(…) 方法注册。
如果想让监听器自动注册,而不关心应用的创建方式,你可以在工程中添加一个 META-INF/spring.factories 文件,并使用 org.springframework.context.ApplicationListener 作为key 指向那些监听器,如下:
# 注册自己的监听器 org.springframework.context.ApplicationListener=com.huangx.springboot.springapplication.MyListener
监听器 MyListener 的代码如下:
import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; public class MyListener implements ApplicationListener { @Override public void onApplicationEvent(ApplicationEvent applicationEvent) { System.out.println("MyListener onApplicationEvent()"); } }
上面介绍了通过 META-INF/spring.factories 文件注册我们的事件,下面将介绍通过 SpringApplication 注册监听器:
import org.springframework.boot.Banner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; @SpringBootApplication public class SpringapplicationDemoApplication { public static void main(String[] args) { SpringApplication app = new SpringApplication(SpringapplicationDemoApplication.class); app.addListeners(new MyListener()); app.setBannerMode(Banner.Mode.OFF); app.run(args); } }
或者,使用 SpringApplicationBuilder 注册监听器,如下:
import org.springframework.boot.Banner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; @SpringBootApplication public class SpringapplicationDemoApplication { public static void main(String[] args) { new SpringApplicationBuilder().sources(ParentApplication.class) .child(SpringapplicationDemoApplication.class) .listeners(new MyListener()) .bannerMode(Banner.Mode.OFF) .run(args); } }
应用运行时,事件会以下面的次序发送:
在运行开始,但除了监听器注册和初始化以外的任何处理之前,会发送一 个 ApplicationStartedEvent
在 Environment 将被用于已知的上下文,但在上下文被创建前,会发送一个 ApplicationEnvironmentPreparedEvent
在refresh开始前,但在bean定义已被加载后,会发送一 个 ApplicationPreparedEvent
在 refresh 之后,相关的回调处理完,会发送一个 ApplicationReadyEvent,表示应用准备好接收请求了
启动过程中如果出现异常,会发送一个 ApplicationFailedEvent
注意:通常不需要使用 application 事件,但知道它们的存在是有用的(在某些场合可能会使用到),比如,在 Spring Boot 内部会使用事件处理各种任务。
该接口由应用程序事件监听器实现,且它继承 java.util.EventListener 接口,是一个标准的 Observer(观察者)设计模式。
从Spring 3.0开始,ApplicationListener 可以一般性地声明其感兴趣的事件类型。向 Spring ApplicationContext 注册后,将相应地过滤事件,并且仅针对匹配事件对象调用侦听器。
接口方法说明:
onApplicationEvent(E event):处理应用程序事件
ApplicationListener<PayloadApplicationEvent<T>> forPayload(Consumer<T> consumer):根据给定的有效 consumer 创建一个新的 ApplicationListener
该类由所有应用程序事件进行扩展,因为直接发布一般事件没有意义。源码如下:
public abstract class ApplicationEvent extends EventObject { /** use serialVersionUID from Spring 1.2 for interoperability. */ private static final long serialVersionUID = 7099057708183571937L; /** System time when the event happened. */ private final long timestamp; /** * Create a new {@code ApplicationEvent}. * @param source the object on which the event initially occurred or with * which the event is associated (never {@code null}) */ public ApplicationEvent(Object source) { super(source); this.timestamp = System.currentTimeMillis(); } /** * Return the system time in milliseconds when the event occurred. */ public final long getTimestamp() { return this.timestamp; } }
在 Spring Boot 中提供了很多 ApplicationEvent 接口的实现,如:AbstractSubProtocolEvent、ApplicationContextEvent、BrokerAvailabilityEvent、PayloadApplicationEvent、RequestHandledEvent、TestContextEvent。我们可以再自己的监听器 onApplicationEvent() 方法中监听你想要监听的事件。
例如:在自己的监听器中监听 ApplicationStartingEvent 事件,代码如下:
import org.springframework.boot.context.event.ApplicationStartingEvent; import org.springframework.context.ApplicationListener; public class MyListener implements ApplicationListener<ApplicationStartingEvent> { @Override public void onApplicationEvent(ApplicationStartingEvent applicationEvent) { System.out.println("MyListener onApplicationEvent()"); } }