当前位置: 首页 > news >正文

Spring监听器(ApplicationEvent):比MQ更轻的异步神器!

“顾客挤爆柜台时,优秀的店长不会催促咖啡师加速,而是启动一套科学的协作机制—— 就像Spring事件驱动,用发布-订阅模式让系统像顶级咖啡团队般优雅应对洪峰流量”

01

咖啡店里的监听器:3位灵魂角色

真实战场还原(每秒1000订单的咖啡店):

publicclassOrderEventextendsApplicationEvent{ // final修饰的订单ID:就像咖啡师绝不涂改的订单小票 privatefinal String orderId; // 创建时间:记录订单诞生时刻(线程安全不可变) privatefinal LocalDateTime createTime = LocalDateTime.now(); // 无setter:防止多线程并发篡改订单 }
@Service publicclassOrderService{ // 店长的麦克风(构造器注入更优雅) privatefinal ApplicationEventPublisher eventPublisher; publicvoidcreateOrder(Order order){ // 核心业务:生成订单(咖啡店接单) eventPublisher.publishEvent(new OrderEvent(this, order.getId())); // 📢 广播订单 } }
@Component publicclassCoffeeMakerListener{ @EventListener @Order(1) // 优先级:先做咖啡再推荐甜点 publicvoidmakeCoffee(OrderEvent event){ // 专注做咖啡,不关心谁结账 log.info("咖啡师:开始制作订单{}的拿铁...", event.getOrderId()); } }
  1. 事件定义:咖啡店的「订单小票」

  2. 事件发布:店长的「广播系统」

  3. 事件监听:咖啡团队的「技能响应」

02

扛住亿级流量的3把利器

场景1:冷启动缓存预加载(防雪崩)

@Component publicclassCachePreloader{ // 在Spring容器"开店准备完成"时触发 @EventListener(ContextRefreshedEvent.class) publicvoidinitCache() { // 异步加载省时30%(实测数据) CompletableFuture.runAsync(() -> { provinceService.loadProvincesToCache(); productService.preloadHotProducts(); }); } }

场景2:事务成功后的缓存清理(保一致性)

// 只在数据库提交成功后执行(避免脏清理) @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) publicvoidcleanCache(OrderUpdateEvent event){ // 异步清理:不阻塞结账队伍 redisTemplate.executeAsync(new RedisCallback<>() { @Override public Void doInRedis(RedisConnection connection){ connection.del(("order:" + event.getId()).getBytes()); returnnull; } }); }

场景3:无侵入式功能扩展

改造前(臃肿的收银台):

publicvoidpay(){ paymentService.pay(); // 核心支付 auditService.log(); // 审计代码入侵 riskService.check(); // 风控代码耦合 marketingService.addPoints(); // 新增需求污染核心 }

事件驱动改造后:

// 纯净支付核心(专注收钱) publicvoidpay(Long orderId){ paymentService.process(orderId); eventPublisher.publishEvent(new PaymentSuccessEvent(orderId)); // 📢 广播支付成功 } // 新增积分模块(无需修改支付代码) @Component publicclassPointListener{ @EventListener publicvoidaddPoints(PaymentSuccessEvent event){ // 积分服务独立演进 pointService.award(event.getOrderId(), 100); } }

03

血泪教训:3个深夜加班事故

事故1:多线程篡改事件(订单混乱)

// 错误!事件必须是只读的 @EventListener publicvoidhandle(OrderEvent event){ event.setStatus("MODIFIED"); // ⚠️ 多线程并发修改引发订单错乱 }

正确做法: 事件类设计为final字段 + 无setter

事故2:异步事件丢失(顾客投诉)

@SpringBootApplication @EnableAsync// 必须显式开启异步 publicclassApplication{ @Bean("eventExecutor") public Executor taskExecutor(){ // 关键参数:拒绝策略用CallerRunsPolicy(避免丢单) ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); return executor; } } // 指定线程池执行 @Async("eventExecutor") @EventListener publicvoidasyncHandle(OrderEvent event){...}

事故3:事件循环调用(咖啡师卡死)

// 错误:在事件处理中发布新事件 @EventListener publicvoidhandleA(EventA a){ publisher.publishEvent(new EventB()); } @EventListener publicvoidhandleB(EventB b){ publisher.publishEvent(new EventA()); // ♻️ 死循环! }

04

关键抉择:监听器 vs MQ 架构对垒

维度

Spring监听器

MQ消息队列

适用场景

单机事务协作 ✅

跨服务通信 ✅

可靠性

进程宕机事件消失 ❌

持久化/重试 ✅

吞吐量

内存级传输,10w+/s 🚀

受网络限制,1w/s ⚠️

开发效率

免搭建MQ,注解即用 ✅

需部署中间件 ❌

数据一致性

本地事务保障 ✅

需分布式事务 ⚠️

黄金决策树:

同JVM事务操作 → Spring监听器(开发效率王炸)

跨服务最终一致 → RocketMQ(可靠性担当)

05

性能调优:监听器的涡轮增压

异步喷射:

@Async// 方法级异步(线程池加速) @EventListener publicvoidasyncProcess(LogEvent event){...}

条件过滤(减少无效处理):

// 只处理VIP客户的订单 @EventListener(condition = "#event.user.level == 'VIP'") publicvoidhandleVipOrder(OrderEvent event){...}

批量处理(Spring 4.2+特性):

// 一次性处理整批订单(提升数据库IO效率) @EventListener publicvoidbatchProcess(List<OrderEvent> events){ orderDao.batchInsert(events.stream().map(OrderConverter::toEntity).toList()); }

06

最佳实践:5条生存法则

1、单一职责原则

一个监听器只做一件事:如 PaymentListener 只处理支付, CouponListener 只发券

2、事件轻量化

禁止在事件中携带 HttpSession 等重型对象(建议只传ID)

3、异常隔离舱

异步事件必须独立捕获异常:

@Async @EventListener publicvoidhandle(Event event){ try { businessLogic(); } catch (Exception e) { // 记录日志 + 告警(防止雪崩) log.error("事件处理失败: {}", event, e); alarmManager.notify(e); } }

4、版本兼容设计

事件类预留版本字段:

publicclassOrderEvent{ privatefinal String version = "1.0"; // 未来可扩展 }
// 监控处理时长/失败率/QPS @Around("@annotation(org.springframework.context.event.EventListener)") public Object monitor(ProceedingJoinPoint pjp){ Timer.Sample sample = Timer.start(); try { return pjp.proceed(); } finally { sample.stop(Metrics.timer("event.process.time")); } }

5、监控三件套

优秀架构的本质不是预测所有需求,而是拥抱变化。

通过Spring事件监听器,我们将系统拆解为可插拔的乐高模块:

  • 新增功能时 → 添加监听器(无需修改核心代码)

  • 流量暴增时 → 开启异步(无需重构架构)

这恰如经营咖啡店的真谛:

“不是雇佣更快的咖啡师,而是设计永不拥堵的协作机制”

程序员彩蛋:

下回当你为需求变更焦头烂额时,不妨问问自己:

“我的代码,像一家应对自如的咖啡店吗?”

附录:性能压测数据(阿里云ECS 8核16G)

模式

吞吐量

平均延迟

CPU占用

同步监听

12,000/s

15ms

85%

异步+批量

98,000/s

2ms

62%

技术选型建议: 万级QPS以内首选Spring事件,超越则上MQ

http://www.jsqmd.com/news/284215/

相关文章:

  • 超级好用的仿真计算,输入参数即可。 cruise与simulink联合仿真计算,一个模型解决纯...
  • 山东服务不错的不锈钢液压设备接头品牌厂家,哪家比较靠谱?
  • 2026最新幼小衔接幼儿园top5评测!服务深度覆盖锦江区、青羊区、双流区等地,辐射成都本地,优质培训学校权威榜单发布,助力儿童平稳过渡小学
  • AuNRs-mPEG5000(808nm,甲氧基聚乙二醇修饰金纳米棒,应用特性
  • 2026年优质工单系统软件、靠谱品牌与资深厂商推荐清单
  • biotin-N3,biotin-azide ,N3-biotin,biotin-PEG-N3,生物素偶联叠氮基
  • 2026年1月最新湖北麻城口碑好的石材厂家推荐
  • 宕机后,Redis如何实现快速恢复?
  • 聊聊启程国际旅行社口碑怎么样,是否值得游客选择
  • Java版LeetCode热题100之单词拆分:从动态规划到面试实战的全面解析
  • 【软考每日一练015】计算机网络:DNS 递归查询与迭代查询解析
  • 2026年最新在线客服软件与系统推荐:全面评测与选择指南
  • 2026医学考研课程排名前十出炉!避坑指南+选课干货全整理
  • 近6亿元!欧洲航天局站台,这家瑞士企业用3D打印重构卫星制造
  • arcGis连不上HighGoDB的解决方案
  • 2026论文降AIGC率工具排行榜,CSDN权威评测AI率狂降至8%,多平台通杀还加密防漏!
  • Java版LeetCode热题100之最长递增子序列:从O(n²)动态规划到O(n log n)贪心+二分的深度剖析
  • 大数据毕业设计选题推荐:基于Spark+Django的旅游评价分析系统源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习 数据挖掘
  • Java版LeetCode热题100之乘积最大子数组:动态规划中的正负博弈与空间优化艺术
  • 2026年高适配工单系统品牌厂商盘点,靠谱推荐清单
  • Java版LeetCode热题100之分割等和子集:从NP完全问题到0-1背包的深度解析
  • 医学考研党必看!这些资料带你稳稳上岸
  • 【译】Visual Studio 2026 来了:更快、更智能,深受老用户的喜爱
  • Java锁优化:从synchronized到CAS的演进与实战选择
  • Java版LeetCode热题100之最长有效括号:三种解法深度剖析与算法思维升华
  • 第六课 · 6.1从 JDBC 到 MyBatis:SQL 工程化是如何发生的?
  • 2026申请香港优才中介机构有哪些:从政策适配到服务全面对比
  • 客船按需定制厂家怎么选?青岛雷旺达船舶是优选
  • 学长亲荐2026TOP10AI论文工具:本科生毕业论文必备测评
  • wsl2使用windows代理