Spring 中的事件驱动模型
事件驱动是 Spring 框架中实现解耦、异步处理和系统集成的重要模式。它基于观察者模式,允许组件之间通过事件进行通信。

- 事件源:用于定义和产生事件对象信息,并把事件对象传递出去
- 监听器:把监听器注册到事件源上,代表对事件源事件对象感兴趣,接收到事件后去处理
事件驱动机制,通过定义和发布事件,将不同组件之间去解耦,使其能够以异步的方式进行通讯。
Spring 事件监听 vs 消息中间件
| 特性 | Spring 事件监听 | 消息中间件 (MQ) |
|---|---|---|
| 通信范围 | 单个 JVM 进程内 | 跨进程、跨服务器、跨网络 |
| 可靠性 | 内存级别,进程重启丢失 | 持久化,高可用 |
| 性能 | 极高(内存操作) | 较高(网络IO) |
| 复杂性 | 简单,Spring 原生支持 | 复杂,需要额外组件 |
| 扩展性 | 单机扩展性好,分布式需额外设计 | 天生支持分布式 |
| 主要用途 | 应用内模块解耦 | 系统间集成、异步处理 |
Spring 事件 - 内存级可靠性
Spring 事件 - 优点
- 执行快,无网络延迟
- 事务集成好(@TransactionalEventListener)
Spring 事件 - 缺点
- JVM 重启 → 内存事件丢失
- 监听器异常可能影响发布者
- 无消息重试机制(除非自己实现)
Spring 事件 - 适合场景
- 业务逻辑的通知
- 不需要持久化的操作
- 事务一致性要求高的场景
消息中间件 - 企业级可靠性
消息中间件 - 优点
- 消息持久化(磁盘存储)
- 高可用(集群部署)
- 消息确认机制(ACK)
- 死信队列(处理失败消息)
- 消息重试
消息中间件 - 缺点
- 网络延迟
- 配置复杂
- 需要额外运维
消息中间件 - 适合场景
- 支付、订单等关键业务
- 跨系统数据同步
- 削峰填谷
内部事件监听
Spring 内置事件的监听,通过 @EventListener 注解实现监听; 注解中如果没有指定事件对象,那么,方法的参数就是感兴趣的对象
案例
1、定义线程池
java
/**
* 事件驱动此线程池配置类
*
* @author 朔风
* @date 2026-01-15 14:33
*/
@EnableAsync
@Configuration
public class EventThreadPoolConfig {
private static final Logger logger = LoggerFactory.getLogger(EventThreadPoolConfig.class);
@Bean("eventAsyncTaskExecutor")
public Executor getAsyncExecutor() {
int cpuCount = Runtime.getRuntime().availableProcessors();
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(cpuCount * 2);
taskExecutor.setMaxPoolSize(cpuCount * 4);
taskExecutor.setQueueCapacity(50_000);
taskExecutor.setKeepAliveSeconds(60);
taskExecutor.setThreadNamePrefix("event-async-");
// 拒绝策略
taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
taskExecutor.setAwaitTerminationSeconds(60);
taskExecutor.initialize();
return taskExecutor;
}
}2、定义事件
java
/**
* 推送事件
*
* @author 朔风
* @date 2026-01-15 14:14
*/
public class PushEvent extends ApplicationEvent {
public PushEvent(Object source) {
super(source);
}
}3、推送事件消息定义
java
/**
* 推送事件消息定义
*
* @author 朔风
* @date 2026-01-15 14:16
*/
public class PushEventMessage {
private Long userId;
private Long pushTime;
private String content;
public PushEventMessage(Long userId, Long pushTime, String content) {
this.userId = userId;
this.pushTime = pushTime;
this.content = content;
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public Long getPushTime() {
return pushTime;
}
public void setPushTime(Long pushTime) {
this.pushTime = pushTime;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public String toString() {
return "PushEventMessage{" +
"userId=" + userId +
", pushTime=" + pushTime +
", content='" + content + '\'' +
'}';
}
}4、定义监听者
推送事件监听,通过实现 ApplicationListener 接口实现对事件的监听
java
/**
* 推送事件监听
* 通过实现 ApplicationListener 接口实现对事件的监听
*
* @author 朔风
* @date 2026-01-15 14:19
*/
@Component
public class PushEventListener01 implements ApplicationListener<PushEvent> {
private static final Logger logger = LoggerFactory.getLogger(PushEventListener01.class);
@Async("eventAsyncTaskExecutor")
@Override
public void onApplicationEvent(PushEvent event) {
PushEventMessage message = (PushEventMessage) event.getSource();
logger.info("PushEventListener01 {}.....", message.toString());
}
}推送事件监听,注解驱动
java
/**
* 推送事件监听,注解驱动
*
* @author 朔风
* @date 2026-01-15 14:22
*/
@Component
public class PushEventListener02 {
private static final Logger logger = LoggerFactory.getLogger(PushEventListener02.class);
@Async("eventAsyncTaskExecutor")
@EventListener(PushEvent.class)
public void receive(PushEvent event) {
PushEventMessage message = (PushEventMessage) event.getSource();
logger.info("PushEventListener02 {} .....", message.toString());
}
}5、推送事件发布
java
/**
* 推送事件发布
*
* @author 朔风
* @date 2026-01-15 14:28
*/
@Component
public class PushEventPublisher {
/* ApplicationContext 继承于 ApplicationEventPublisher */
private final ApplicationContext applicationContext;
private final ApplicationEventPublisher publisher;
public PushEventPublisher(ApplicationContext applicationContext, ApplicationEventPublisher publisher) {
this.applicationContext = applicationContext;
this.publisher = publisher;
}
/***
* 事件发布
*
* @author 朔风
* @date 2026/1/15 14:29
* @param message message
* @return void
*/
public void publish(PushEventMessage message) {
/* 第一种方式 */
applicationContext.publishEvent(new PushEvent(message));
/* 第二种方式 */
publisher.publishEvent(new PushEvent(message));
}
}
剑鸣秋朔