Spring事件机制:解耦利器与实战

一、为什么需要事件机制?
在传统的业务开发中,我们经常会遇到这样的场景:
scss
// 传统方式:强耦合
@Service
public class OrderService {
@Autowired
private EmailService emailService;
@Autowired
private SmsService smsService;
@Autowired
private InventoryService inventoryService;
@Autowired
private PointsService pointsService;
public void createOrder(Order order) {
// 1. 保存订单
orderRepository.save(order);
// 2. 发送邮件
emailService.sendOrderConfirmation(order);
// 3. 发送短信
smsService.sendNotification(order);
// 4. 扣减库存
inventoryService.deductStock(order);
// 5. 增加积分
pointsService.addPoints(order.getUserId(), order.getAmount());
}
}
这种方式存在严重问题:
- 强耦合:OrderService依赖太多服务
- 难维护:新增业务需要修改OrderService
- 不灵活:无法动态添加/移除业务逻辑
- 性能差:所有操作同步执行
Spring事件机制优雅地解决了这些问题!

二、Spring事件机制核心概念
Spring事件机制基于观察者模式,包含三个核心角色:
1. 事件(Event)
- 继承
ApplicationEvent的POJO类 - 携带业务数据
2. 事件发布者(Publisher)
- 通过
ApplicationEventPublisher发布事件 - 通常是业务服务类
3. 事件监听器(Listener)
- 使用
@EventListener或实现ApplicationListener - 处理特定类型的事件
工作流程:
rust
发布者 --发布事件--> Spring容器 --分发--> 监听器1
└--分发--> 监听器2
└--分发--> 监听器3
三、基础使用
3.1 定义事件
scala
/**
* 订单创建事件
*/
public class OrderCreatedEvent extends ApplicationEvent {
private final Order order;
public OrderCreatedEvent(Object source, Order order) {
super(source);
this.order = order;
}
public Order getOrder() {
return order;
}
}
3.2 发布事件
scss
/**
* 订单服务 - 事件发布者
*/
@Service
public class OrderService {
private final ApplicationEventPublisher eventPublisher;
private final OrderRepository orderRepository;
public OrderService(ApplicationEventPublisher eventPublisher,
OrderRepository orderRepository) {
this.eventPublisher = eventPublisher;
this.orderRepository = orderRepository;
}
public Order createOrder(OrderRequest request) {
// 1. 核心业务:保存订单
Order order = new Order();
order.setUserId(request.getUserId());
order.setAmount(request.getAmount());
order = orderRepository.save(order);
// 2. 发布事件
eventPublisher.publishEvent(new OrderCreatedEvent(this, order));
return order;
}
}
3.3 监听事件
csharp
/**
* 邮件服务 - 事件监听器
*/
@Component
public class EmailEventListener {
private final EmailService emailService;
public EmailEventListener(EmailService emailService) {
this.emailService = emailService;
}
@EventListener
public void handleOrderCreated(OrderCreatedEvent event) {
Order order = event.getOrder();
emailService.sendOrderConfirmation(order);
System.out.println("邮件已发送:订单号 " + order.getId());
}
}
/**
* 短信服务 - 事件监听器
*/
@Component
public class SmsEventListener {
private final SmsService smsService;
public SmsEventListener(SmsService smsService) {
this.smsService = smsService;
}
@EventListener
public void handleOrderCreated(OrderCreatedEvent event) {
Order order = event.getOrder();
smsService.sendNotification(order);
System.out.println("短信已发送:订单号 " + order.getId());
}
}
/**
* 库存服务 - 事件监听器
*/
@Component
public class InventoryEventListener {
private final InventoryService inventoryService;
public InventoryEventListener(InventoryService inventoryService) {
this.inventoryService = inventoryService;
}
@EventListener
public void handleOrderCreated(OrderCreatedEvent event) {
Order order = event.getOrder();
inventoryService.deductStock(order);
System.out.println("库存已扣减:订单号 " + order.getId());
}
}
效果对比:
- OrderService只负责核心业务,完全解耦
- 新增监听器无需修改OrderService
- 监听器可以动态添加/移除
四、高级特性

4.1 异步事件
默认情况下,事件是同步处理的。使用@Async可以异步处理:
less
/**
* 开启异步支持
*/
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean
public Executor asyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("event-async-");
executor.initialize();
return executor;
}
}
/**
* 异步监听器
*/
@Component
public class AsyncEventListener {
@EventListener
@Async
public void handleOrderCreatedAsync(OrderCreatedEvent event) {
System.out.println("异步处理开始,线程:" + Thread.currentThread().getName());
// 耗时操作
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("异步处理完成");
}
}
4.2 条件监听
使用SpEL表达式实现条件监听:
csharp
@Component
public class ConditionalEventListener {
// 只处理金额大于1000的订单
@EventListener(condition = "#event.order.amount > 1000")
public void handleLargeOrder(OrderCreatedEvent event) {
System.out.println("处理大额订单:" + event.getOrder().getAmount());
}
// 只处理VIP用户的订单
@EventListener(condition = "#event.order.userType == 'VIP'")
public void handleVipOrder(OrderCreatedEvent event) {
System.out.println("处理VIP订单");
}
}
4.3 事件监听顺序
使用@Order控制监听器执行顺序:
java
@Component
public class OrderedEventListener {
@EventListener
@Order(1)
public void firstListener(OrderCreatedEvent event) {
System.out.println("第一个执行");
}
@EventListener
@Order(2)
public void secondListener(OrderCreatedEvent event) {
System.out.println("第二个执行");
}
@EventListener
@Order(3)
public void thirdListener(OrderCreatedEvent event) {
System.out.println("第三个执行");
}
}
4.4 泛型事件
Spring 4.2+支持泛型事件:
typescript
/**
* 泛型事件基类
*/
public class EntityEvent<T> extends ApplicationEvent {
private final T entity;
private final EventType type;
public EntityEvent(Object source, T entity, EventType type) {
super(source);
this.entity = entity;
this.type = type;
}
public T getEntity() {
return entity;
}
public EventType getType() {
return type;
}
public enum EventType {
CREATED, UPDATED, DELETED
}
}
/**
* 泛型监听器
*/
@Component
public class GenericEventListener {
// 只监听User类型的创建事件
@EventListener
public void handleUserCreated(EntityEvent<User> event) {
if (event.getType() == EntityEvent.EventType.CREATED) {
System.out.println("用户创建:" + event.getEntity().getName());
}
}
// 只监听Product类型的事件
@EventListener
public void handleProductEvent(EntityEvent<Product> event) {
System.out.println("产品事件:" + event.getType());
}
}
4.5 事务事件
Spring提供了事务事件监听:
java
@Component
public class TransactionalEventListener {
// 事务提交后执行
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void handleAfterCommit(OrderCreatedEvent event) {
System.out.println("事务已提交,发送通知");
}
// 事务回滚后执行
@TransactionalEventListener(phase = TransactionPhase.AFTER_ROLLBACK)
public void handleAfterRollback(OrderCreatedEvent event) {
System.out.println("事务已回滚,记录日志");
}
// 事务完成后执行(无论提交还是回滚)
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMPLETION)
public void handleAfterCompletion(OrderCreatedEvent event) {
System.out.println("事务已完成");
}
// 事务提交前执行
@TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT)
public void handleBeforeCommit(OrderCreatedEvent event) {
System.out.println("事务即将提交");
}
}
五、实战应用场景

5.1 用户注册场景
java
/**
* 用户注册事件
*/
public class UserRegisteredEvent extends ApplicationEvent {
private final User user;
public UserRegisteredEvent(Object source, User user) {
super(source);
this.user = user;
}
public User getUser() {
return user;
}
}
/**
* 用户服务
*/
@Service
public class UserService {
private final ApplicationEventPublisher eventPublisher;
private final UserRepository userRepository;
public UserService(ApplicationEventPublisher eventPublisher,
UserRepository userRepository) {
this.eventPublisher = eventPublisher;
this.userRepository = userRepository;
}
@Transactional
public User registerUser(UserRegisterRequest request) {
// 1. 创建用户
User user = new User();
user.setUsername(request.getUsername());
user.setEmail(request.getEmail());
user.setPassword(encodePassword(request.getPassword()));
user = userRepository.save(user);
// 2. 发布事件
eventPublisher.publishEvent(new UserRegisteredEvent(this, user));
return user;
}
private String encodePassword(String password) {
// 密码加密逻辑
return password;
}
}
/**
* 欢迎邮件监听器
*/
@Component
public class WelcomeEmailListener {
@EventListener
@Async
public void sendWelcomeEmail(UserRegisteredEvent event) {
User user = event.getUser();
// 发送欢迎邮件
System.out.println("发送欢迎邮件给:" + user.getEmail());
}
}
/**
* 赠送新人礼包监听器
*/
@Component
public class NewUserGiftListener {
@EventListener
@Async
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void giveNewUserGift(UserRegisteredEvent event) {
User user = event.getUser();
// 赠送新人礼包
System.out.println("赠送新人礼包给用户:" + user.getUsername());
}
}
/**
* 初始化用户配置监听器
*/
@Component
public class UserConfigInitListener {
@EventListener
@Order(1)
public void initUserConfig(UserRegisteredEvent event) {
User user = event.getUser();
// 初始化用户配置
System.out.println("初始化用户配置:" + user.getId());
}
}
5.2 文章发布场景
less
/**
* 文章发布事件
*/
public class ArticlePublishedEvent extends ApplicationEvent {
private final Article article;
public ArticlePublishedEvent(Object source, Article article) {
super(source);
this.article = article;
}
public Article getArticle() {
return article;
}
}
/**
* 文章服务
*/
@Service
public class ArticleService {
private final ApplicationEventPublisher eventPublisher;
@Transactional
public void publishArticle(Long articleId) {
// 1. 更新文章状态为已发布
Article article = articleRepository.findById(articleId).orElseThrow();
article.setStatus(ArticleStatus.PUBLISHED);
article.setPublishTime(LocalDateTime.now());
articleRepository.save(article);
// 2. 发布事件
eventPublisher.publishEvent(new ArticlePublishedEvent(this, article));
}
}
/**
* 搜索索引更新监听器
*/
@Component
public class SearchIndexListener {
@EventListener
@Async
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void updateSearchIndex(ArticlePublishedEvent event) {
Article article = event.getArticle();
// 更新ElasticSearch索引
System.out.println("更新搜索索引:" + article.getTitle());
}
}
/**
* 缓存预热监听器
*/
@Component
public class CacheWarmUpListener {
@EventListener
@Async
public void warmUpCache(ArticlePublishedEvent event) {
Article article = event.getArticle();
// 预热Redis缓存
System.out.println("预热缓存:" + article.getId());
}
}
/**
* 通知订阅者监听器
*/
@Component
public class SubscriberNotificationListener {
@EventListener
@Async
public void notifySubscribers(ArticlePublishedEvent event) {
Article article = event.getArticle();
// 通知订阅该作者的用户
System.out.println("通知订阅者:新文章《" + article.getTitle() + "》");
}
}
5.3 支付成功场景
less
/**
* 支付成功事件
*/
public class PaymentSuccessEvent extends ApplicationEvent {
private final Payment payment;
public PaymentSuccessEvent(Object source, Payment payment) {
super(source);
this.payment = payment;
}
public Payment getPayment() {
return payment;
}
}
/**
* 支付服务
*/
@Service
public class PaymentService {
private final ApplicationEventPublisher eventPublisher;
@Transactional
public void processPayment(PaymentRequest request) {
// 1. 处理支付
Payment payment = new Payment();
payment.setOrderId(request.getOrderId());
payment.setAmount(request.getAmount());
payment.setStatus(PaymentStatus.SUCCESS);
paymentRepository.save(payment);
// 2. 发布事件
eventPublisher.publishEvent(new PaymentSuccessEvent(this, payment));
}
}
/**
* 订单状态更新监听器
*/
@Component
public class OrderStatusUpdateListener {
@EventListener
@Order(1)
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void updateOrderStatus(PaymentSuccessEvent event) {
Payment payment = event.getPayment();
// 更新订单状态为已支付
System.out.println("更新订单状态:" + payment.getOrderId());
}
}
/**
* 发货通知监听器
*/
@Component
public class ShipmentListener {
@EventListener
@Order(2)
@Async
public void notifyWarehouse(PaymentSuccessEvent event) {
Payment payment = event.getPayment();
// 通知仓库发货
System.out.println("通知仓库发货:订单" + payment.getOrderId());
}
}
/**
* 积分奖励监听器
*/
@Component
public class PointsRewardListener {
@EventListener
@Async
public void awardPoints(PaymentSuccessEvent event) {
Payment payment = event.getPayment();
// 根据支付金额奖励积分
int points = payment.getAmount().intValue() / 10;
System.out.println("奖励积分:" + points);
}
}
六、与消息队列对比

| 特性 | Spring事件机制 | 消息队列(RabbitMQ/Kafka) |
|---|---|---|
| 作用范围 | 单应用内 | 跨应用、分布式 |
| 持久化 | 不支持 | 支持 |
| 可靠性 | 一般 | 高 |
| 性能 | 高(内存) | 中等(网络IO) |
| 学习成本 | 低 | 中等 |
| 适用场景 | 应用内解耦 | 微服务间通信 |
使用建议:
- 单体应用内部解耦 → Spring事件机制
- 微服务间通信 → 消息队列
- 两者可以结合使用
七、最佳实践

7.1 推荐做法
1. 事件命名规范
scala
// ✅ 推荐:使用过去式,表示已发生的事件
public class OrderCreatedEvent extends ApplicationEvent { }
public class PaymentSuccessEvent extends ApplicationEvent { }
public class UserRegisteredEvent extends ApplicationEvent { }
// ❌ 不推荐
public class CreateOrderEvent extends ApplicationEvent { }
public class PayEvent extends ApplicationEvent { }
2. 事件数据封装
scala
// ✅ 推荐:封装必要的业务数据
public class OrderCreatedEvent extends ApplicationEvent {
private final Order order;
private final Long userId;
private final LocalDateTime createTime;
// 构造器、getter
}
// ❌ 不推荐:只传递ID
public class OrderCreatedEvent extends ApplicationEvent {
private final Long orderId; // 监听器需要再查询数据库
}
3. 异步处理非核心业务
less
// ✅ 推荐:非核心业务异步处理
@Component
public class NotificationListener {
@EventListener
@Async
public void sendNotification(OrderCreatedEvent event) {
// 发送通知是非核心业务,异步处理
}
}
// ❌ 不推荐:核心业务异步处理
@Component
public class PaymentListener {
@EventListener
@Async // 支付是核心业务,不应异步
public void processPayment(OrderCreatedEvent event) {
// 处理支付
}
}
4. 使用事务事件监听
less
// ✅ 推荐:需要数据库持久化的操作使用事务事件
@Component
public class StockListener {
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void deductStock(OrderCreatedEvent event) {
// 确保订单事务提交后才扣减库存
}
}
// ❌ 不推荐:可能导致数据不一致
@Component
public class StockListener {
@EventListener
public void deductStock(OrderCreatedEvent event) {
// 订单事务可能回滚,但库存已扣减
}
}
7.2 避免的陷阱
1. 避免循环事件
typescript
// ❌ 危险:可能导致无限循环
@Component
public class EventA {
@Autowired
private ApplicationEventPublisher publisher;
@EventListener
public void handleB(EventB event) {
publisher.publishEvent(new EventA()); // 触发EventA
}
}
@Component
public class EventB {
@Autowired
private ApplicationEventPublisher publisher;
@EventListener
public void handleA(EventA event) {
publisher.publishEvent(new EventB()); // 触发EventB,形成循环!
}
}
// ✅ 解决方案:添加防重标记
public class EventA extends ApplicationEvent {
private boolean processed = false;
}
2. 避免监听器中的长时间阻塞
typescript
// ❌ 不推荐:同步监听器执行耗时操作
@Component
public class SlowListener {
@EventListener
public void slowProcess(OrderCreatedEvent event) {
Thread.sleep(10000); // 阻塞10秒
// 所有后续监听器都要等待
}
}
// ✅ 推荐:耗时操作异步处理
@Component
public class FastListener {
@EventListener
@Async
public void asyncProcess(OrderCreatedEvent event) {
Thread.sleep(10000); // 不阻塞其他监听器
}
}
八、性能优化

8.1 使用异步处理
typescript
@Configuration
@EnableAsync
public class AsyncEventConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(200);
executor.setThreadNamePrefix("event-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return (ex, method, params) -> {
log.error("异步事件处理异常: method={}, params={}",
method.getName(), Arrays.toString(params), ex);
};
}
}
8.2 批量处理事件
csharp
/**
* 批量处理事件
*/
@Component
public class BatchEventProcessor {
private final List<OrderCreatedEvent> eventQueue = new CopyOnWriteArrayList<>();
private static final int BATCH_SIZE = 100;
@EventListener
public void collectEvent(OrderCreatedEvent event) {
eventQueue.add(event);
if (eventQueue.size() >= BATCH_SIZE) {
processBatch();
}
}
@Scheduled(fixedDelay = 5000)
public void processBatch() {
if (eventQueue.isEmpty()) {
return;
}
List<OrderCreatedEvent> batch = new ArrayList<>(eventQueue);
eventQueue.clear();
// 批量处理
System.out.println("批量处理 " + batch.size() + " 个事件");
}
}
8.3 监控事件处理
java
/**
* 事件处理监控
*/
@Aspect
@Component
public class EventListenerMonitor {
@Around("@annotation(org.springframework.context.event.EventListener)")
public Object monitorEventListener(ProceedingJoinPoint pjp) throws Throwable {
String methodName = pjp.getSignature().getName();
long startTime = System.currentTimeMillis();
try {
Object result = pjp.proceed();
long duration = System.currentTimeMillis() - startTime;
if (duration > 1000) {
log.warn("事件监听器执行缓慢: method={}, duration={}ms",
methodName, duration);
}
return result;
} catch (Exception e) {
log.error("事件监听器执行失败: method={}", methodName, e);
throw e;
}
}
}
九、总结
Spring事件机制是一个强大的解耦工具,合理使用能够显著提升代码的可维护性和扩展性。
核心要点:
- 解耦业务:发布者和监听器完全解耦
- 灵活扩展:新增监听器无需修改发布者
- 异步处理:支持异步处理提升性能
- 事务集成:与Spring事务无缝集成
适用场景:
- ✅ 单体应用内部解耦
- ✅ 一对多的业务通知
- ✅ 非核心业务异步处理
- ✅ 审计日志、统计分析
不适用场景:
- ❌ 微服务间通信(用消息队列)
- ❌ 需要持久化的消息(用消息队列)
- ❌ 强一致性要求(同步调用)