Spring事件_发布&监听(2)_笔记

在 Spring事件_发布&监听_笔记 里,介绍了Spring 事件的发布-监听流程。那么,ApplicationEventPublisher.publishEvent() 调用后,会发生什么?

1. 事件发布流程

ApplicationEventPublisher.publishEvent()发布事件流程:

  1. 事件发布 :调用 publishEvent() 方法
  2. 事件分发 :Spring 容器查找所有匹配的 @EventListener 方法
  3. 同步执行 :默认情况下,事件监听器会同步执行(在同一个线程中)
  4. 异常传播 :如果监听器抛出异常,会传播回 publishEvent() 调用处

2. 发布结果与监听的关系

2.1 发布\&监听 默认为同步行为

默认情况下,发布publishEvent() 的成功与否直接取决于 @EventListener 方法的执行结果。

java 复制代码
// 发布事件
try {
    applicationEventPublisher.publishEvent(event.toEvent());
    // 如果监听器抛异常,这里不会执行
    System.out.println("事件发布成功");
} catch (Exception e) {
    // 监听器的异常会在这里被捕获
    System.out.println("事件处理失败: " + e.getMessage());
}
java 复制代码
//监听事件
@Component
public class MyEventListener {
    @EventListener
    public void handleMyEvent(MyEvent event) {
        // 如果这里抛出异常
        throw new RuntimeException("处理失败");
        // 发布处 applicationEventPublisher.publishEvent() 调用会失败
    }
}

2.2 异步处理(解耦)

如果希望事件发布与监听器执行解耦,可以使用 @Async:

java 复制代码
@Component
public class MyEventListener {
    
    @EventListener
    @Async  // 需要启用 @EnableAsync
    public void handleMyEvent(MyEvent event) {
        // 异常不会影响 applicationEventPublisher.publishEvent() 的返回
        throw new RuntimeException("处理失败"); // 这个异常不会传播到发布方
    }
}
java 复制代码
@Configuration
@EnableAsync
public class AsyncConfig {
    // 配置异步执行器
}

3. 关键要点总结

场景 publishEvent() 结果 监听器异常影响
同步(默认) 可能失败 直接影响发布结果
异步(@Async) 总是成功 不影响发布结果

最佳实践

  1. 需要事务一致性:使用同步监听器,确保事件处理失败时可以回滚
  2. 解耦和性能:使用异步监听器,避免阻塞主业务流程
  3. 错误处理:在监听器中添加适当的异常处理逻辑
  4. 监控:对于异步监听器,需要额外的监控机制来跟踪处理结果

所以,在默认同步模式下,publishEvent() 的成功与否直接取决于 @EventListener 方法的执行结果。

相关推荐
霸道流氓气质21 分钟前
RAG 可观测性与生产监控实战:四层遥测模型、五大仪表盘与 OpenTelemetry 全链路追踪的 Java 生产级实现
java·人工智能·python
AOI小白新手上路26 分钟前
autodl常用的tar 打包下载(数据集)命令手册:逐段拆解与套用模板
java·大数据·数据库
xian_wwq40 分钟前
【学习笔记】Milvus 如何完成一次向量相似度检索,Milvus 索引到底应该怎么选?-15
笔记·学习·milvus
dishugj2 小时前
系统架构风险点、敏感点和权衡点的概念和区分
java·开发语言
苜蓿muxu2 小时前
常用代码命名规范
java
马优晨3 小时前
JAVA 中 VO 实体类是什么意思,为什么要做这个
java·开发语言·状态模式·java vo·java vo是什么
Baron X3 小时前
Eclipse Temurin 21 (JRE) Alpine 镜像获取、离线导入与推送操作
java·docker·eclipse·temurin
孙浩君3 小时前
我用 Spring Boot + xterm.js 写了个终端风格互动叙事游戏引擎:游戏即文件,上传一个 JSON 就能玩
java
jose3 小时前
URL 里多写了一个端口,为什么请求还能调通?
java·后端