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

ApplicationListener 实战示例

ApplicationListener 是 Spring 事件驱动模型的核心接口,通过它可以监听容器发布的各种事件,实现组件间的松耦合通信。以下是它的常见用法:

1. 监听 Spring 内置生命周期事件和springboot容器启动周期事件

Spring 容器在启动、刷新、停止、关闭等阶段会发布相应事件,通过监听这些事件可以在特定时机执行初始化或清理工作。

ContextRefreshedEvent‌:容器初始化或刷新完成时触发,此时所有单例 Bean 已就绪。常用于加载缓存、启动定时任务等。
ContextStartedEvent‌:调用容器的 start() 方法时触发,可用于重启已停止的模块。
ContextStoppedEvent‌:调用容器的 stop() 方法时触发,适合暂停正在进行的任务。
ContextClosedEvent‌:容器关闭时触发,适合释放资源、关闭连接等清理操作。
ApplicationReadyEvent:spring boot 容器特有,应用完全启动就绪时触发。

示例:实现 ApplicationListener 并重写 onApplicationEvent,即可在容器刷新完成后执行自定义逻辑。

2. 自定义业务事件,实现业务解耦

当某个业务操作完成后需要触发一系列后续处理(如发短信、记日志、更新缓存),可以通过自定义事件将核心逻辑与附加逻辑分离。

定义事件‌:继承 ApplicationEvent,添加业务数据字段。
创建监听器‌:实现 ApplicationListener<自定义事件>,在 onApplicationEvent 中编写处理逻辑。
发布事件‌:通过注入 ApplicationEventPublisher 或直接使用 ApplicationContext.publishEvent() 发布事件。

这样,订单创建、用户注册等场景只需发布一个事件,对应的监听器就会自动执行后续操作,无需在核心代码中耦合这些逻辑。

3. 使用@EventListener注解简化监听

从 Spring 4.2 开始,可以在任意 Bean 的公开方法上使用@EventListener注解来声明事件监听器,无需实现 ApplicationListener 接口。

方法参数指定监听的事件类型,支持多个事件类型。
可以配合@Async实现异步处理,配合@Order控制执行顺序。
还可以通过@TransactionalEventListener绑定事务阶段(如事务提交后执行)。

这种方式代码更简洁,是目前推荐的做法。

4. 异步事件处理

默认情况下,事件监听器在发布事件的线程中同步执行。如果事件处理耗时较长,可以开启异步支持,避免阻塞主流程。

在监听方法上添加@Async注解,并启用 Spring 的异步执行能力(如 @EnableAsync)。
异步监听器将在独立的线程池中执行,提升系统的响应速度。

5. 控制监听器的执行顺序

当多个监听器监听同一事件时,可以通过@Order注解或实现 Ordered 接口来指定执行顺序。数值越小,优先级越高,越先执行。

6. 事务绑定事件监听

在数据库操作场景中,有时需要确保事件仅在事务成功提交后才触发(例如发送消息通知)。可以使用@TransactionalEventListener注解,并指定事务阶段(默认为 AFTER_COMMIT),这样监听器会在事务提交后执行,避免因事务回滚而产生不一致。

7. 在 Spring Boot 中通过 spring.factories 自动注册

在 Spring Boot 应用中,可以将自定义监听器的全限定类名配置在META-INF/spring.factories文件中:

org.springframework.context.ApplicationListener=com.example.MyListener

这样监听器会被自动加载,无需额外添加 @Component 等注解。

8. 监听 Web 特定事件

在 Web 应用中,还可以监听 RequestHandledEvent(或更具体的 ServletRequestHandledEvent),该事件在每次 HTTP 请求处理完成后发布,可用于记录请求日志、统计性能等。

这些用法覆盖了从容器生命周期管理到业务解耦、异步处理、事务绑定等常见场景,合理运用能显著提升系统的可扩展性和可维护性。

以下是ApplicationListener 的实战示例,从容器生命周期监听到业务解耦,覆盖最常见的应用场景。

一、监听容器刷新完成,执行初始化逻辑

这是最常用的内置事件监听场景。当 Spring 容器中所有单例 Bean 都初始化完毕后,ContextRefreshedEvent 会被发布,非常适合做缓存预热、数据预加载等操作。

importorg.springframework.context.ApplicationListener;importorg.springframework.context.event.ContextRefreshedEvent;importorg.springframework.stereotype.Component;@ComponentpublicclassContextRefreshListenerimplementsApplicationListener<ContextRefreshedEvent>{@OverridepublicvoidonApplicationEvent(ContextRefreshedEventevent){System.out.println("容器刷新完成,开始初始化操作");System.out.println("已加载的Bean数量: "+event.getApplicationContext().getBeanDefinitionCount());// 执行初始化逻辑initCache();preloadData();}privatevoidinitCache(){// 将热点数据加载到 Redis 或本地缓存System.out.println("缓存预热完成");}privatevoidpreloadData(){// 预加载字典表、配置项等System.out.println("数据预加载完成");}}

注意‌:如果应用中存在父子容器(比如 Spring MVC 的 DispatcherServlet 会创建子容器),ContextRefreshedEvent 可能会触发两次。可以通过判断 event.getApplicationContext() 是否为根容器来避免重复执行。

二、自定义业务事件,实现订单创建后的解耦处理

这是一个非常经典的业务解耦案例。订单创建成功后,需要发短信、发邮件、记日志等,如果全部写在 createOrder 方法里,代码会越来越臃肿。用事件机制就能把核心逻辑和附加逻辑彻底分开。
核心概念:
1.事件:extends ApplicationEvent 的类或者普通的对象(Spring 4.2+支持)
2.发布者:使用ApplicationEventPublisher 或者 ApplicationContext 来发布事件。
3.监听者:implements ApplicationListener<事件> 或者 使用@EventListener。

1. 定义事件
importorg.springframework.context.ApplicationEvent;publicclassOrderCreatedEventextendsApplicationEvent{privatefinalLongorderId;privatefinalStringcustomerEmail;privatefinalStringphoneNumber;publicOrderCreatedEvent(Objectsource,LongorderId,StringcustomerEmail,StringphoneNumber){super(source);this.orderId=orderId;this.customerEmail=customerEmail;this.phoneNumber=phoneNumber;}publicLonggetOrderId(){returnorderId;}publicStringgetCustomerEmail(){returncustomerEmail;}publicStringgetPhoneNumber(){returnphoneNumber;}}
2. 创建多个监听器(各司其职)
importorg.springframework.context.ApplicationListener;importorg.springframework.stereotype.Component;// 监听器1:发送短信@ComponentpublicclassSmsNotificationListenerimplementsApplicationListener<OrderCreatedEvent>{@OverridepublicvoidonApplicationEvent(OrderCreatedEventevent){System.out.println("发送短信到 "+event.getPhoneNumber()+":订单 "+event.getOrderId()+" 已创建成功!");// 调用短信服务接口...}}// 监听器2:发送邮件@ComponentpublicclassEmailNotificationListenerimplementsApplicationListener<OrderCreatedEvent>{@OverridepublicvoidonApplicationEvent(OrderCreatedEventevent){System.out.println("发送确认邮件到 "+event.getCustomerEmail()+":订单 "+event.getOrderId()+" 详情...");// 调用邮件服务接口...}}// 监听器3:记录审计日志@ComponentpublicclassAuditLogListenerimplementsApplicationListener<OrderCreatedEvent>{@OverridepublicvoidonApplicationEvent(OrderCreatedEventevent){System.out.println("记录审计日志:订单 "+event.getOrderId()+" 已创建");// 写入审计日志表...}}
3. 在业务代码中发布事件
importorg.springframework.context.ApplicationEventPublisher;importorg.springframework.stereotype.Service;@Service@RequiredArgsConstructorpublicclassOrderService{privatefinalApplicationEventPublishereventPublisher;publicvoidcreateOrder(){// 1. 核心业务:生成订单并保存到数据库LongorderId=12345L;System.out.println("订单 "+orderId+" 已生成并保存到数据库");// 2. 发布事件,后续的短信、邮件、日志由监听器异步/同步处理OrderCreatedEventevent=newOrderCreatedEvent(this,orderId,"user@example.com","13800138000");eventPublisher.publishEvent(event);//也可以注入ApplicationContext ,不推荐,相当于大炮打蚊子//private final ApplicationContext applicationContext ,//applicationContext.publishEvent(event);System.out.println("订单创建主流程结束");}}

这样一来,后续如果还要加「发放优惠券」「推送消息到 App」等逻辑,只需新增一个监听器即可,完全不用改动 OrderService 的核心代码。

三、使用 @EventListener 注解(更简洁的写法)

从 Spring 4.2 开始,不必实现 ApplicationListener 接口,直接用注解就能声明监听器,代码更简洁。

importorg.springframework.context.event.EventListener;importorg.springframework.stereotype.Component;@ComponentpublicclassOrderEventHandler{@EventListenerpublicvoidhandleOrderCreated(OrderCreatedEventevent){System.out.println("[注解方式] 收到订单创建事件,订单ID: "+event.getOrderId());// 处理逻辑...}}

还可以配合 @Async 实现异步处理,配合 @Order 控制执行顺序:

importorg.springframework.context.event.EventListener;importorg.springframework.core.annotation.Order;importorg.springframework.scheduling.annotation.Async;importorg.springframework.stereotype.Component;@ComponentpublicclassAsyncOrderEventHandler{@Async@EventListener@Order(1)publicvoidhandleOrderCreated(OrderCreatedEventevent){System.out.println("[异步处理] 订单 "+event.getOrderId()+" 的后置处理,不阻塞主线程");}}

四、事务绑定事件监听

有时需要确保事件‌只在数据库事务成功提交后才触发‌(比如发消息通知),否则事务回滚了消息却发出去了,就会造成数据不一致。这时用 @TransactionalEventListener:

importorg.springframework.stereotype.Component;importorg.springframework.transaction.event.TransactionPhase;importorg.springframework.transaction.event.TransactionalEventListener;@ComponentpublicclassTransactionalOrderHandler{@TransactionalEventListener(phase=TransactionPhase.AFTER_COMMIT)publicvoidhandleOrderCreatedAfterCommit(OrderCreatedEventevent){System.out.println("事务已提交,安全发送MQ消息,订单ID: "+event.getOrderId());// 发送消息到消息队列...}@TransactionalEventListener(phase=TransactionPhase.AFTER_ROLLBACK)publicvoidhandleOrderCreatedAfterRollback(OrderCreatedEventevent){System.out.println("事务已回滚,记录异常,订单ID: "+event.getOrderId());// 补偿或告警逻辑...}}

五、总结对比

场景推荐方式关键点
容器启动后初始化实现 ApplicationListener注意父子容器重复触发问题
业务解耦(同步)@EventListener 或实现接口代码简洁,推荐注解方式
业务解耦(异步)@Async + @EventListener需启用 @EnableAsync
事务提交后处理@TransactionalEventListener避免事务回滚导致数据不一致
控制执行顺序@Order 注解数值越小越先执行
http://www.jsqmd.com/news/916909/

相关文章:

  • 2026北京黄金回收靠谱榜单 5.29高端变现实测与行业避坑解析 - 资讯纵览
  • QMCDecode:重构你的QQ音乐数字资产自由
  • VSCode远程开发避坑实录:连接Docker容器时SSH端口映射与root登录的那些‘坑’
  • 2026年佛山阻尼铰链与隐藏滑轨厂家同类品类细致比对:顺德源头工厂怎么选才不踩坑? - 企业名录优选推荐
  • CSDN独家整理:BuildingAI 应用场景全解析——智能客服、电商设计、信息流投放
  • 北京黄金回收去哪卖靠谱?2026年5月三大平台实测+避坑指南,这家真的零套路 - 资讯纵览
  • TRALY深海鲨鱼鱼油三代vs一代:成分差异与养护实效对比 - 互联网科技品牌测评
  • 2026年山东区域汽车故障精修机构口碑推荐榜单:德系豪车维修、发动机异常、悬挂问题靠谱门店优选参考 - 海棠依旧大
  • 从Python到C语言:在乐高SPIKE Prime上解锁嵌入式开发与性能优化
  • WeChatIntercept终极指南:macOS微信防撤回插件完整使用教程
  • 全网公认新疆第一贴心!导游娇娇,把游客当家人全程暖心陪护 - 盛世西域旅行
  • CS336 Assignment 1 BPE分词器训练初版(朴素版基础上优化)及后续优化方向分析
  • 2026报考指南:四川省内比较好的大学推荐 - 品牌2025
  • 揭秘26年山东一卡通回收流程中的小技巧,轻松搞定! - 团团收购物卡回收
  • SteamAutoCrack项目深度解析:如何从零构建自动化游戏破解工具
  • 2026 年广州装修公司权威榜单|本土实力与口碑企业汇总 - 商业新知
  • 保姆级教程:用Vue2 + AntV X6 + Element UI 快速搭建一个可拖拽的流程图编辑器
  • 银泰百货卡回收常见问题解答!2026新手最全答疑攻略 - 可可收公众号
  • 2026昆明婚纱摄影品牌速览:现代经典高端婚纱摄影的实力拆解与最新客片 - 生活测评君
  • 如何判断闲置银泰百货卡的回收价格是否合理? - 团团收购物卡回收
  • 力扣刷题#1:两数之和_从暴力解法到哈希表优化
  • 2026年佛山阻尼铰链与隐藏滑轨厂家全方位实力对标:全屋定制五金一站式选购避坑教程 - 企业名录优选推荐
  • VoiceFixer终极教程:3分钟学会AI语音修复,让模糊录音变清晰
  • 基于Arduino与PIR传感器的互动游戏装置设计与实现
  • 【技术管理】技术选型方法论:从需求到落地的决策指南
  • 三步解决B站视频下载难题:哔哩下载姬完全使用指南
  • 2026报考指南:四川文化艺术学院校园环境与设施介绍 - 品牌2025
  • 2026年美国移民公司深度解析:如何选择专业服务机构 - 品牌排行榜
  • 2026义乌公司注册代办执照集群地址托管十大实力星榜:本土服务商深度测评 - 企业品牌优选推荐官
  • AI智能体人才招引实操指南:破局人才缺口,构建区域AI产业优势