👋 前言
前面我们已经详细探讨了:IOC、生命周期、循环依赖、AOP、事务、SpringMVC、Boot 自动配置、资源加载与 Environment。
Spring 内部也存在靠事件驱动解耦的机制:容器启动、刷新、容器刷新(refresh)完成后发布 ContextRefreshedEvent,此时所有 Bean 均已初始化完毕,是最常用的启动后逻辑入口......这一篇我们梳理事件模型,了解掌握 Spring 轻量但极其重要的扩展机制。
即刻起,简单又轻松。
一、核心角色
- ApplicationEvent:事件本身(所有事件的父类)
- ApplicationListener:事件监听器(观察者)
- ApplicationEventPublisher:事件发布器(被观察者)
- ApplicationContext:本身就是发布器,内部维护监听器
- ApplicationEventMulticaster :Spring 通过
AbstractApplicationContext.initApplicationEventMulticaster()方法初始化事件多播器。默认创建的是SimpleApplicationEventMulticaster实例;同时还承担了事件匹配和路由的重要职责------它需要根据事件类型找到对应的监听器进行派发
二、最简流程
- 定义事件
extends ApplicationEvent(经典方式)- 直接使用任意 POJO
- 定义监听器
implements ApplicationListener - 容器启动时收集所有监听器
- 调用
publishEvent发布 - Spring 遍历匹配监听器执行
onApplicationEvent
三、Spring 内置核心事件
| 事件类型 | 触发时机 |
|---|---|
ContextRefreshedEvent |
容器完全刷新完成(Bean 都初始化好了) |
ContextStartedEvent |
容器启动 |
ContextStoppedEvent |
容器停止 |
ContextClosedEvent |
容器关闭(单例 Bean 销毁前) |
RequestHandledEvent |
SpringMVC 请求处理完成 |
最常用 :ContextRefreshedEvent,很多框架启动逻辑都监听它。
四、源码级流程:事件是怎么被发布和消费的?
核心调用链
java
// 1. 发布入口
publishEvent(Object event)
↓
// 2. 获取事件类型,包装为 ApplicationEvent(若 event 本身不是)
getApplicationEventMulticaster()
↓
// 3. 多播器开始派发
multicastEvent(ApplicationEvent event, ResolvableType eventType)
↓
// 4. 获取所有匹配的监听器
getApplicationListeners(event, type)
↓
// 5. 遍历监听器,逐个调用
invokeListener(listener, event)
↓
// 6. 最终执行监听器的回调
listener.onApplicationEvent(event)
1. 发布入口:publishEvent
几乎所有地方最终都会走到:
java
// AbstractApplicationContext
protected void publishEvent(Object event, @Nullable ResolvableType typeHint) {
// 1. 包装成 ApplicationEvent
ApplicationEvent applicationEvent = null;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
} else {
applicationEvent = new PayloadApplicationEvent<>(this, event);
}
// 2. 获取多播器
ApplicationEventMulticaster multicaster = this.applicationEventMulticaster;
// 3. 多播事件:发给所有匹配监听器
multicaster.multicastEvent(applicationEvent, typeHint);
}
2. 事件多播核心:SimpleApplicationEventMulticaster
java
@Override
public void multicastEvent(ApplicationEvent event, @Nullable ResolvableType typeHint) {
ResolvableType eventType = (typeHint != null ? typeHint : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
for (ApplicationListener<?> listener : getApplicationListeners(event, eventType)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
} else {
invokeListener(listener, event);
}
}
}
3. 最终执行监听器
java
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
listener.onApplicationEvent(event);
}
五、@EventListener 注解原理
1. 解析器:EventListenerMethodProcessor
EventListenerMethodProcessor 实现 SmartInitializingSingleton 接口,在容器所有单例 Bean 完成实例化、依赖注入、初始化之后,执行 afterSingletonsInstantiated()。
SmartInitializingSingleton.afterSingletonsInstantiated()的触发时机是"所有单例 Bean 实例化完成之后的一次性回调;而实例化、依赖注入、初始化是 bean 生命周期中更早阶段发生的事情。
2. 核心流程
- 遍历所有单例 Bean
- 找出带
@EventListener的方法 - 解析监听的事件类型
- 包装成
ApplicationListenerMethodAdapter - 注册到
ApplicationEventMulticaster
3. 执行时
发布事件 → 匹配 adapter → 反射调用你写的 @EventListener 方法。
六、异步事件 @Async + 事件
Spring 事件默认是同步执行的(发布者线程阻塞直到所有监听器执行完毕)。
开启步骤
全局异步(所有事件都异步)
重写 applicationEventMulticaster Bean,为其设置 TaskExecutor:
配置后,所有事件的派发都会提交到线程池中执行,发布者线程立即返回。
java
@Configuration
public class AsyncEventConfig {
@Bean(name = "applicationEventMulticaster")
public ApplicationEventMulticaster applicationEventMulticaster() {
SimpleApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster();
multicaster.setTaskExecutor(Executors.newFixedThreadPool(5)); // 设置线程池
return multicaster;
}
}
局部异步
-
启动类加
@EnableAsyncjava@EnableAsync // 启动类或配置类上添加 @SpringBootApplication public class Application { ... } -
监听方法上加
@Asyncjava@Component public class OrderEventListener { @Async // 仅此监听器异步执行 @EventListener public void handleOrder(OrderEvent event) { // 异步处理逻辑 } } -
配置
TaskExecutorBean(可选但强烈建议配置)
可自定义 TaskExecutor Bean 控制线程池,不配置则使用默认的 SimpleAsyncTaskExecutor(每个任务新建线程,不推荐生产环境使用)。
原理
多播时判断有 executor 就提交线程池,不阻塞主线程。
七、事务绑定事件 @TransactionalEventListener
核心 :TransactionSynchronization
若发布事件时不存在事务,默认直接执行,可通过
fallbackExecution控制。
原理
- 不立即执行监听方法
- 把执行逻辑挂到事务同步管理器
- 等事务 提交 / 回滚 / 完成 后再执行
常用阶段
BEFORE_COMMITAFTER_COMMITAFTER_ROLLBACKAFTER_COMPLETION
这是微服务 / 分布式事务里非常实用的 "事务完成后再发消息" 方案。
八、Spring 事件完整总结
| 组件 | 说明 |
|---|---|
| 事件 | ApplicationEvent |
| 监听 | ApplicationListener / @EventListener |
| 发布 | ApplicationContext.publishEvent |
| 调度 | ApplicationEventMulticaster |
| 异步 | @Async + TaskExecutor |
| 事务绑定 | @TransactionalEventListener |
| 内置事件 | 启动 / 刷新 / 停止 / 关闭 |
轻量、解耦、无侵入,是 Spring 内部和业务扩展最常用的机制之一。