一、Spring 事件驱动完整流程总结
1. 定义事件:基类封装 + 业务事件继承
(1)事件基类:TestEvent(继承 Spring 标准 ApplicationEvent )
作用:封装通用事件数据,作为所有相关事件的父类,减少重复代码。
核心:继承 ApplicationEvent,通过构造器传递事件源(source) 和通用业务数据(cmd),并提供 getter 供子类 / 监听器获取。
java
// 事件基类:封装通用事件数据(可根据业务选择是否需要通用事件封装)
public class TestEvent extends ApplicationEvent {
@Getter
private CommonTestData cmd;
// 构造器:必传事件源 + 通用业务数据
public TestEvent(Object source, CommonTestData cmd) {
super(source); // 调用父类ApplicationEvent构造器,绑定事件源
this.cmd = cmd;
}
}
(2)业务事件:RealTimeTestEvent(继承 TestEvent)
作用:基于基类扩展,定义具体业务场景的事件,无需重复封装通用数据。
核心:直接复用父类 TestEvent 的构造器,仅传递业务所需参数,简化事件定义。
java
// 业务事件:继承TestEvent,专注业务场景
public class RealTimeTestEvent extends TestEvent {
// 直接复用父类构造器,传递事件源 + 业务数据cmd
public RealTimeTestEvent(Object source, CommonTestData cmd) {
super(source, cmd);
}
}
2. 发布事件:业务方法中触发
注入 Spring 内置 ApplicationEventPublisher,在核心业务逻辑完成后发布事件。
可通过开关(如 isTestEventTestEnable)控制是否发布,灵活适配业务需求。
java
@Autowired
private ApplicationEventPublisher eventPublisher;
// 业务方法中发布事件(核心逻辑执行后)
if (isTestEventTestEnable) {
// 构造业务事件,传递事件源(this) + 业务数据md
eventPublisher.publishEvent(new RealTimeTestEvent(this, md));
}
3. 监听事件:异步监听 + 自定义线程池
监听器类加 @Service(或 @Component),被 Spring 容器管理。
用 @EventListener 绑定具体事件,@Async 指定自定义线程池,实现异步非阻塞处理。
从事件中通过 getCmd() 获取通用业务数据,执行附加逻辑。
java
@Slf4j
@Service
public class RealTimeTestEventListener {
@SneakyThrows
// 1. 指定自定义线程池,异步执行(不阻塞主线程)
@Async("RealTimeTestEventThreadPool")
// 2. 监听RealTimeTestEvent事件(匹配事件类型)
@EventListener(RealTimeTestEvent.class)
public void handleEvent(RealTimeTestEvent event) {
// 从事件基类TestEvent中获取通用业务数据
CommonTestData md = event.getCmd();
// 执行业务附加逻辑
MktDataTestRealTimeListener.pushRealTimeTest(
...
);
}
}
4. 线程池配置:自定义隔离 + 动态参数
用 @Configuration 声明配置类,@Bean 定义线程池,供 @Async 调用。
从配置文件读取线程池参数(核心数、最大数、队列容量),支持动态调整。
设置线程名前缀,方便日志排查;配置拒绝策略(如 CallerRunsPolicy)避免任务丢失。
java
@Configuration
public class TestEventThreadPool {
@Autowired
private ThreadPoolProperties threadPoolProperties;
// 定义线程池Bean,指定名称供@Async调用
@Bean("realTimeTestEventThreadPool")
public Executor realTimeTestEventThreadPool() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
// 动态读取配置参数
taskExecutor.setCorePoolSize(threadPoolProperties.getRealTimeTest().getCoreSize());
taskExecutor.setMaxPoolSize(threadPoolProperties.getRealTimeTest().getMaxPoolSize());
taskExecutor.setQueueCapacity(threadPoolProperties.getRealTimeTest().getQueueCapacity());
// 通用配置:线程名前缀、拒绝策略等
taskExecutor.setThreadNamePrefix("realTimeTestEventThreadPool--");
taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 初始化线程池
taskExecutor.initialize();
return taskExecutor;
}
}
二、@EventListener vs @TransactionalEventListener:核心区别与适用场景
1. 核心区别(一句话总结)
@EventListener:事件发布即执行,不依赖事务状态;
@TransactionalEventListener:绑定事务阶段执行(如事务提交后),专为事务场景设计。
2.关键事务阶段(phase)
@TransactionalEventListener 支持 4 种事务阶段,按需选择:
TransactionPhase.BEFORE_COMMIT:事务提交前执行(慎用,可能阻塞事务提交);
TransactionPhase.AFTER_COMMIT:事务提交成功后执行(最常用,保证数据一致性);
TransactionPhase.AFTER_ROLLBACK:事务回滚后执行(如回滚补偿逻辑);
TransactionPhase.AFTER_COMPLETION:事务完成后(无论提交 / 回滚)执行。
3. 适用场景选型(结合你的业务)
(1)用 @EventListener 的场景
业务无数据库事务,或事务与事件处理无数据依赖;不操作数据库,无数据一致性风险,用 @EventListener 更简洁高效。
事件处理是轻量操作(如推送消息、记录日志、更新缓存),无需等待事务提交;
(2)用 @TransactionalEventListener 的场景
事件处理依赖主事务的数据库数据(如主事务更新数据后,监听器需读取最新数据);
需避免 "事务未提交,监听器读取脏数据" 的问题;
三、整体核心价值总结
代码复用:通过 TestEvent 基类封装通用事件数据,业务事件仅需继承,减少重复代码;
业务解耦:主业务只负责发布事件,监听器独立处理附加逻辑,新增 / 删除逻辑无需修改主业务;
性能优化:@Async + 自定义线程池,让附加逻辑异步执行,不阻塞主线程,提升接口响应速度;
稳定性保障:自定义线程池控制并发,避免默认线程池的 OOM 风险;@TransactionalEventListener 解决事务场景的数据一致性问题;
灵活扩展:支持多事件、多监听器、多线程池隔离,适配复杂业务场景。
四、快速选型口诀
非事务、轻量处理、无数据依赖 → 用 @EventListener;
事务场景、需读最新事务数据、保证一致性 → 用 @TransactionalEventListener(phase = AFTER_COMMIT)。
五、Spring 事件驱动和消息中间件选型
(1)、Spring 事件驱动:仅适用于同一个服务(进程内) 本地解耦
Spring 事件驱动(ApplicationEvent/@EventListener/@TransactionalEventListener)的底层是基于 Spring 容器的内存事件广播机制,事件的发布、监听全程都在同一个 JVM 进程内完成,无法跨服务、跨进程、跨服务器传递。
核心价值:解决单服务内部的业务解耦问题;
优势:轻量、无中间件依赖、执行效率高、无需考虑网络 / 序列化问题;
局限:仅单服务有效,服务集群部署时,事件仅在当前发布事件的服务实例中触发,其他实例无法感知。
(2)、跨服务解耦:必须使用消息中间件(主流选型)
当需要跨服务、跨进程、跨服务器传递事件 / 消息时,Spring 事件驱动完全无法满足,此时消息中间件(MQ) 是标准且唯一的解决方案,其核心作用是实现分布式系统中的异步通信与解耦。
主流消息中间件选型(按场景适配):
RabbitMQ:基于 AMQP 协议,支持丰富的消息路由(直连、主题、扇出等)、消息确认、死信队列,适配复杂的业务场景(如订单支付后跨服务通知库存、物流),企业级项目首选;
Kafka:基于发布 - 订阅模式,高吞吐、低延迟、高可用,适合大数据量、高并发的日志收集、实时数据同步、流处理场景;
RocketMQ:阿里开源,兼顾 RabbitMQ 的功能丰富性和 Kafka 的高吞吐,支持分布式事务消息,适合电商、金融等核心业务场景;
ActiveMQ:老牌消息中间件,协议支持全面,但性能和高可用略逊于前三者,适合中小型项目或传统项目。