一、价值
Spring Boot和Spring 事件是SpringApplication整个生命周期重要环节
二、Spring Boot事件发布
1.切入点
Spring Boot和Spring 事件的触发发生在SpringApplication运行阶段,围绕run(String…)方法不同阶段触发。run(String…)结合SpringApplication初始化阶段完成的相关状态,进一步完善了运行时所需要准备的资源,随后启动Spring应用上下文,在此期间就会伴随Spring Boot和Spring 事件的触发
2. 源码(SpringBoot 2.0和1.0有一定的差别但不大,截图为2.0源码):
3.SpringApplicationRunListeners:
按照源码逻辑的实现,SpringApplicationRunListeners是有getRunListeners(String[] args)方法创建的,SpringApplicationRunListeners属于组合模式的实现,重点在其内部关联SpringApplicationRunListener集合
5.SpringApplicationRunListener:
SpringApplicationRunListener为Spring Boot应用运行时监听器,其监听方法被SpringApplicationRunListeners迭代执行。
监听方法有:
监听方法 | 运行时阶段说明 | 事件 |
---|---|---|
starting() | Spring应用刚启动 | ApplicationStartingEvent |
environmentPrepared(ConfigurableEnvironment) | ConfigurableEnvironment准备妥当,允许将其调整 | ApplicationEnvironmentPreparedEvent |
contextPrepared(ConfigurableApplicationContext) | ConfigurableApplicationContext准备妥当,允许将其调整 | 无 |
contextLoaded(ConfigurableApplicationContext) | ConfigurableApplicationContext已装载,但未启动 | ApplicationPreparedEvent |
started(ConfigurableApplicationContext) | ConfigurableApplicationContext已启动,此时Spring Bean已初始化完成 | ApplicationStartedEvent |
running(ConfigurableApplicationContext ) | Spring应用正在运行 | ApplicationReadyEvent |
failed(ConfigurableApplicationContext context, Throwable exception) | Spring应用运行失败 | ApplicationFailedEvent |
4.SpringApplicationRunListener内建实现
- 结合SpringFactoriesLoader机制,能快速定位到其内建实现:EventPublishingRunListener,而且是唯一实现
- 将SpringApplication初始化阶段关联的ApplicationListener实例列表动态的添加到SimpleApplicationEventMulticaster对象中。SimpleApplicationEventMulticaster源于Spring Framework,从源码可以看出实现ApplicationEventMulticaster接口,用于发布Spring应用事件(ApplicationEvent)。因此EventPublishingRunListener实际是作为Spring Boot事件发布者
四、Spring 事件发布
-
ApplicationEventMulticaster注册ApplicationListener UML如下:
本质上就是将ApplicationEvent与ApplicationListener集合进行关联,因此AbstractApplicationEventMulticaster#getApplicationListeners(
ApplicationEvent event, ResolvableType eventType)方法返回event关联ApplicationListener集合。具体可查看源码 -
ApplicationEventMulticaster事件广播
主要涉及两个方法:multicastEvent(ApplicationEvent event)和multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType),两个这方法均在SimpleApplicationEventMulticaster中实现并且是唯一实现。 -
ApplicationContext事件发布
从uml文件可以看出ApplicationContext的子接口ConfigurableApplicationContext提供了添加ApplicationListenner实例方法:addApplicationListener(ApplicationListener<?> listener).
故ApplicationContext通过调用publishEvent(ApplicationEvent event)发布事件 -
Spring 内建事件
事件 | 介绍 | 描述 |
---|---|---|
ContextRefreshedEvent | Spring应用上下文就绪事件 | 当ConfigurableApplicationContext#refresh()方法执行到finishRefresh()方法时,发布ContextRefreshedEvent。此时Spring应用上下文中bean均已完成初始化,可以通过监听该事件获取需要Bean,防止出现Bean提早初始化所带来的的风险 |
ContextStartedEvent | Spring应用上下文启动事件(大多数场景基本不会触发) | AbstractApplicationContext#start()时触发,同时能回调Lifecycle Bean的生命周期 |
ContextStoppedEvent | Spring应用上下文停止事件(大多数场景基本不会触发) | AbstractApplicationContext#stop()时触发,同时能回调Lifecycle Bean的生命周期 |
ContextClosedEvent | Spring应用上下文关闭事件 | ConfigurableApplicationContext#close()时触发,由子类AbstractApplicationContext实现,执行close()后当前Spring应用上下文完全被销毁,无法恢复(这和调用stop()有本质的区别) |
5.Spring应用上下文事件ApplicationContextEvent和Spring 内建时间关系如下:
六、run(String…)执行过程中各事件发布点以及顺序(Spring Boot 2.0.8)
序号 | 监听方法 | 运行时阶段说明 | 事件 |
---|---|---|---|
1 | starting() | Spring应用刚启动 | ApplicationStartingEvent |
2 | environmentPrepared(ConfigurableEnvironment) | ConfigurableEnvironment准备妥当,允许将其调整 | ApplicationEnvironmentPreparedEvent |
3 | prepareContext(…)->contextPrepared(ConfigurableApplicationContext) | ConfigurableApplicationContext准备与装载 | 无 |
4 | contextLoaded(ConfigurableApplicationContext) | ConfigurableApplicationContext已装载,但未启动 | ApplicationPreparedEvent |
5 | refreshContext(context)->AbstractApplicationContext#rrefresh(ApplicationContext)->finishRefresh() | ConfigurableApplicationContext启动以及Spring Bean初始化,执行完毕后,Spring应用上下文正式进入Spring生命周期,Spring Boot核心特性也随之启动例如组件自动装配、嵌入式容器启动、Production-Ready特性 | ContextRefreshedEvent |
6 | started(ConfigurableApplicationContext) | ConfigurableApplicationContext已启动,此时Spring Bean已初始化完成 | ApplicationStartedEvent |
7 | running(ConfigurableApplicationContext ) | Spring应用正在运行 | ApplicationReadyEvent |
8 | failed(ConfigurableApplicationContext context, Throwable exception) | Spring应用运行失败 | ApplicationFailedEvent |
代码验证(Spring Boot 2.0.8)
public static void main(String[] args) {
new SpringApplicationBuilder(Object.class)
.listeners(event ->
System.out.printf("监听到事件: %s , 事件源 : %s\n"
, event.getClass().getSimpleName(), event.getSource())
)
.web(false)
.run(args)
.close();
}
结果:(注意Spring Boot和Spring 事件源)