目录
2. ApplicationEventPublisher:事件发布器
一、什么是Spring事件机制?
Spring事件驱动模型是基于观察者模式的实现,包含三大核心组件:
与传统方法调用的对比:
特性 | 直接方法调用 | 事件驱动模型 |
---|---|---|
耦合度 | 紧耦合 | 松耦合 |
扩展性 | 修改调用方 | 新增监听器即可 |
执行方式 | 同步阻塞 | 支持异步 |
适用场景 | 简单流程 | 跨模块协作 |
二、四大核心组件解析
1. ApplicationEvent:事件对象
// 自定义用户注册事件
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;
}
}
2. ApplicationEventPublisher:事件发布器
@Service
public class UserService {
private final ApplicationEventPublisher publisher;
public UserService(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
public void registerUser(User user) {
// 1. 用户注册逻辑
userRepository.save(user);
// 2. 发布事件
publisher.publishEvent(new UserRegisteredEvent(this, user));
}
}
3. ApplicationListener:事件监听接口
// 传统实现方式(实现接口)
@Component
public class EmailNotificationListener
implements ApplicationListener<UserRegisteredEvent> {
@Override
public void onApplicationEvent(UserRegisteredEvent event) {
sendWelcomeEmail(event.getUser());
}
private void sendWelcomeEmail(User user) {
// 发送欢迎邮件逻辑
}
}
4. @EventListener:注解驱动监听
@Component
public class BonusService {
@EventListener // 注解方式更简洁
public void handleUserRegistered(UserRegisteredEvent event) {
grantSignupBonus(event.getUser());
}
private void grantSignupBonus(User user) {
// 发放注册奖励
}
}
三、五种事件处理方式详解
方式1:接口实现(传统方式)
@Component
public class LoggingListener implements ApplicationListener<ApplicationEvent> {
private static final Logger log = LoggerFactory.getLogger(LoggingListener.class);
@Override
public void onApplicationEvent(ApplicationEvent event) {
log.info("收到事件: {}", event.getClass().getSimpleName());
}
}
适用场景:全局事件监控
方式2:注解方式(推荐)
@Component
public class UserActivityListener {
@EventListener // 自动匹配事件类型
public void onUserLogin(UserLoginEvent event) {
// 记录登录日志
}
@EventListener
public void onUserLogout(UserLogoutEvent event) {
// 清理会话信息
}
}
方式3:条件过滤
@EventListener(condition = "#event.user.vipLevel >= 3")
public void handleVipEvent(UserRegisteredEvent event) {
// 仅处理VIP用户事件
}
方式4:事务绑定
@TransactionalEventListener(
phase = TransactionPhase.AFTER_COMMIT // 事务提交后执行
)
public void afterOrderCommit(OrderCreatedEvent event) {
// 发送订单确认邮件(确保事务成功)
}
方式5:异步处理
@Async // 启用异步执行
@EventListener
public void asyncHandleEvent(DataExportEvent event) {
// 执行耗时导出操作
}
四、Spring内置事件解析
事件类型 | 触发时机 | 典型应用场景 |
---|---|---|
ContextRefreshedEvent | ApplicationContext初始化或刷新 | 缓存预热,资源初始化 |
ContextStartedEvent | ApplicationContext启动 | 启动后台服务 |
ContextStoppedEvent | ApplicationContext停止 | 释放资源,暂停任务 |
ContextClosedEvent | ApplicationContext关闭 | 清理资源,关闭连接池 |
RequestHandledEvent | HTTP请求处理完成 | 请求耗时统计 |
内置事件监听示例:
@Component
public class SystemListener {
@EventListener
public void handleContextRefresh(ContextRefreshedEvent event) {
// 初始化系统配置
ConfigLoader.loadAll();
}
@EventListener
public void handleContextClose(ContextClosedEvent event) {
// 优雅关闭资源
ConnectionPool.releaseAll();
}
}
五、企业级应用场景
场景1:用户注册全流程
// 用户服务
public void registerUser(User user) {
userDao.save(user);
publisher.publishEvent(new UserRegisteredEvent(user));
}
// 监听器1:发送邮件
@EventListener
public void sendWelcomeEmail(UserRegisteredEvent event) { ... }
// 监听器2:发放优惠券
@EventListener
public void grantCoupon(UserRegisteredEvent event) { ... }
// 监听器3:推荐关系绑定
@EventListener
public void bindReferral(UserRegisteredEvent event) { ... }
场景2:订单状态变更通知
@EventListener
public void onOrderPaid(OrderPaidEvent event) {
// 1. 更新库存
stockService.reduce(event.getOrder());
// 2. 通知商家
merchantService.notifyNewOrder(event.getOrder());
// 3. 触发物流
logisticsService.createDelivery(event.getOrder());
}
场景3:系统配置热更新
// 发布配置更新事件
public void updateConfig(Config config) {
configDao.update(config);
publisher.publishEvent(new ConfigUpdatedEvent(config));
}
// 各模块响应更新
@EventListener
public void refreshCache(ConfigUpdatedEvent event) {
cacheManager.refresh(event.getConfigKey());
}
@EventListener
public void reloadRuleEngine(ConfigUpdatedEvent event) {
if (event.isRuleChange()) {
ruleEngine.reload();
}
}
六、高级特性实战
1. 事件继承机制
// 基础事件
public abstract class AbstractPaymentEvent extends ApplicationEvent {
private final Payment payment;
// 构造方法
}
// 具体事件
public class PaymentSuccessEvent extends AbstractPaymentEvent { ... }
public class PaymentFailedEvent extends AbstractPaymentEvent { ... }
// 监听基类事件
@EventListener
public void handlePaymentEvent(AbstractPaymentEvent event) {
// 处理所有支付相关事件
}
2. 有序事件监听
@EventListener
@Order(1) // 数字越小优先级越高
public void validateOrder(OrderSubmitEvent event) {
// 1. 订单验证
}
@EventListener
@Order(2)
public void calculatePrice(OrderSubmitEvent event) {
// 2. 价格计算
}
@EventListener
@Order(3)
public void saveOrder(OrderSubmitEvent event) {
// 3. 持久化订单
}
3. 事务事件传播
@TransactionalEventListener(
phase = TransactionPhase.AFTER_COMMIT, // 事务提交后
fallbackExecution = true // 无事务时也执行
)
public void auditLog(AuditEvent event) {
// 审计日志(必须确保记录成功)
}
七、性能优化与生产实践
1. 异步事件配置
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("Event-Async-");
executor.initialize();
return executor;
}
}
// 使用示例
@Async
@EventListener
public void asyncEventHandler(ReportGeneratedEvent event) { ... }
2. 事件监控
@Bean
public ApplicationEventMulticaster applicationEventMulticaster() {
SimpleApplicationEventMulticaster multicaster =
new SimpleApplicationEventMulticaster();
// 添加监控拦截器
multicaster.addApplicationListener(event -> {
monitorService.logEvent(event);
});
return multicaster;
}
3. 错误处理机制
@Component
public class GlobalEventListenerExceptionHandler {
@EventListener
public void handleException(ListenerExecutionFailedEvent event) {
Throwable ex = event.getException();
log.error("事件处理失败: {}", event.getEvent(), ex);
// 告警通知
}
}
八、常见问题解决方案
问题1:事件未触发
排查步骤:
确认事件发布方法是否执行
检查监听器是否被Spring管理(@Component)
验证事件类型与监听器参数类型匹配
检查条件表达式是否过滤
问题2:循环事件依赖
// 错误示例:事件中发布新事件
@EventListener
public void handleEventA(EventA event) {
publisher.publishEvent(new EventB()); // 危险操作!
}
// 解决方案:使用异步处理
@Async
@EventListener
public void handleEventA(EventA event) {
// 安全发布新事件
}
问题3:事件丢失
解决方案:
// 1. 使用事务事件监听器
@TransactionalEventListener(phase = AFTER_COMMIT)
// 2. 添加持久化事件日志
@EventListener
public void logEvent(ApplicationEvent event) {
eventLogRepository.save(new EventLog(event));
}
九、最佳实践总结
-
事件设计原则:
-
事件命名:
<业务对象><动作>Event
(如OrderPaidEvent) -
携带数据:事件对象包含业务处理所需的最小数据集
-
单一职责:一个事件只代表一个业务动作
-
-
监听器规范:
@Async // 耗时操作异步化 @Order(Ordered.HIGHEST_PRECEDENCE) // 明确执行顺序 @TransactionalEventListener(phase = AFTER_COMMIT) // 事务敏感操作 @EventListener(condition = "#event.valid") // 条件过滤 public void handleEvent(CustomEvent event) { // 异常捕获 try { // 业务逻辑 } catch (Exception ex) { // 错误处理 } }
-
生产环境建议:
-
关键业务事件添加持久化日志
-
为异步事件配置独立线程池
-
实现事件监控大盘
-
定期审计事件链路
-
架构价值:
Spring事件机制将系统拆分为事件生产者和事件消费者,通过事件总线解耦模块,是构建现代响应式系统的基石