Spring Event 观察者模型及事件和消息队列之间的区别笔记

Spring Event观察者模型:基于内置事件实现自定义监听

在Spring框架中,观察者模式通过事件驱动模型实现,允许组件间通过事件发布与监听进行解耦通信。这一机制的核心在于ApplicationEventApplicationListenerApplicationEventPublisher等接口的协作,结合Spring容器的事件广播器(如ApplicationEventMulticaster),能够高效管理事件的生命周期。

Spring的事件机制通过观察者模式实现了组件间的松耦合通信。开发者可通过自定义事件与监听器灵活扩展业务逻辑,同时利用同步/异步模式优化性能。一般结合事务绑定和泛型支持,可以利用这个机制在复杂系统中展现出强大的灵活性和可维护性。


Spring事件模型的核心组件

事件(ApplicationEvent)

所有事件的基类,自定义事件需继承此类。例如:

   public class MyCustomEvent extends ApplicationEvent {private String data;public MyCustomEvent(Object source, String data) {super(source);this.data = data;}}

事件类可携带业务数据,供监听器处理。

事件发布者(ApplicationEventPublisher)

通过publishEvent()方法发布事件。Spring容器会自动注入ApplicationEventPublisher实例,或通过实现ApplicationEventPublisherAware接口获取:

   @Componentpublic class EventPublisher {@Autowiredprivate ApplicationEventPublisher publisher;public void publish(String data) {publisher.publishEvent(new MyCustomEvent(this, data));}}

事件监听器(ApplicationListener)

监听器可通过两种方式实现:
接口实现:继承ApplicationListener并指定泛型事件类型:

     @Componentpublic class CustomListener implements ApplicationListener<MyCustomEvent> {@Overridepublic void onApplicationEvent(MyCustomEvent event) {System.out.println("Received: " + event.getData());}}

注解驱动:使用@EventListener标注方法,支持灵活的事件类型匹配:

     @Componentpublic class AnnotatedListener {@EventListenerpublic void handleEvent(MyCustomEvent event) {// 处理逻辑}}

事件广播器(ApplicationEventMulticaster)

默认实现类为SimpleApplicationEventMulticaster,负责将事件分发给所有匹配的监听器。可通过配置其TaskExecutor实现异步事件处理。


实现自定义事件监听的步骤

定义事件类

继承ApplicationEvent并封装业务数据,例如订单创建事件:

   public class OrderCreatedEvent extends ApplicationEvent {private Order order;public OrderCreatedEvent(Object source, Order order) {super(source);this.order = order;}}

发布事件

在业务逻辑中注入ApplicationEventPublisher并调用其publishEvent()方法:

   @Servicepublic class OrderService {@Autowiredprivate ApplicationEventPublisher publisher;public void createOrder(Order order) {// 业务逻辑publisher.publishEvent(new OrderCreatedEvent(this, order));}}

监听事件
方式一:实现接口
适用于需要强类型事件绑定的场景:

     @Componentpublic class OrderListener implements ApplicationListener<OrderCreatedEvent> {@Overridepublic void onApplicationEvent(OrderCreatedEvent event) {sendNotification(event.getOrder());}}

方式二:使用注解
支持方法参数自动推导事件类型,更简洁:

     @Componentpublic class NotificationService {@EventListenerpublic void onOrderCreated(OrderCreatedEvent event) {// 发送通知}}

异步处理配置

默认事件处理是同步的。若要异步执行,需配置广播器:

   @Configurationpublic class AsyncEventConfig {@Beanpublic ApplicationEventMulticaster eventMulticaster() {SimpleApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster();multicaster.setTaskExecutor(new SimpleAsyncTaskExecutor());return multicaster;}}

高级特性与注意事项

事务绑定事件(@TransactionalEventListener)

若事件需在事务提交后触发,可使用此注解,并指定phase参数:

   @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)public void handleAfterCommit(OrderPaidEvent event) {// 事务提交后的处理}
TransactionPhase枚举类 
package org.springframework.transaction.event;public enum TransactionPhase {BEFORE_COMMIT,// 在提交之前AFTER_COMMIT,// 在提交之后AFTER_ROLLBACK,// 在回滚之后AFTER_COMPLETION;// 在完成之后private TransactionPhase() {}
} 

泛型事件处理
Spring通过ResolvableType支持泛型事件的分发,例如监听EntityCreatedEvent<Order>

异常处理

通过实现ErrorHandler接口,可统一处理监听器中的异常。


作用

解耦业务逻辑:例如用户注册后发送邮件与短信,通过事件拆分可避免代码耦合。
异步任务处理:如日志记录、数据同步等耗时操作,通过异步监听提升性能。
系统状态监听:例如容器启动(ContextRefreshedEvent)时初始化缓存。


事件(ApplicationEvent)与MQ的核心区别解析

在软件架构中, 事件(ApplicationEvent)消息队列(MQ) 均用于实现组件间的解耦通信,但两者的设计目标、技术实现和适用场景存在显著差异。
事件机制与MQ的本质区别在于通信边界可靠性设计。事件机制是轻量级的进程内解耦工具,适合单体应用;MQ则是分布式系统中实现高可靠、跨系统通信的基石。


作用范围与通信边界

维度事件(ApplicationEvent)MQ(如RabbitMQ、Kafka)
通信范围仅限同一Spring容器内的组件通信(单体应用内部)支持跨系统、跨进程、跨语言的分布式通信
数据一致性依赖本地事务,易与Spring事务管理器集成(如@TransactionalEventListener依赖MQ的事务消息或最终一致性机制(如RabbitMQ的Confirm模式)
适用场景单体应用内的模块解耦(如用户注册后触发邮件发送)分布式系统间的异步通信(如订单系统与库存系统的交互)

核心差异

事件机制是进程内通信工具,基于观察者模式实现轻量级解耦;MQ是跨进程/跨系统的中间件,通过消息代理实现分布式系统间的可靠通信。


技术实现与架构特性

通信模型

事件机制
基于Spring的ApplicationEventPublisher发布事件,ApplicationListener@EventListener监听处理。
默认同步执行(监听器按顺序触发),但可通过ApplicationEventMulticaster配置异步线程池实现异步处理。

MQ
采用生产者-消费者模型,依赖Broker(如RabbitMQ的Exchange/Queue)进行消息路由。
天然支持异步通信,消费者可独立处理消息,实现流量削峰和负载均衡。

可靠性

事件机制
无持久化机制,若系统崩溃或监听器抛出异常,事件可能丢失。
需通过ErrorHandler自定义异常处理逻辑。

MQ
提供消息持久化、重试机制、死信队列(DLQ)等保障可靠性。
例如RabbitMQ支持消息确认(ACK/NACK)和事务消息,确保消息至少被消费一次

扩展性

事件机制
监听器数量增加可能导致性能下降(同步模式下),需谨慎设计异步处理。
无法直接扩展为分布式系统。

MQ
支持横向扩展(如Kafka的分区机制),可应对高并发场景。
天然适应微服务架构,支持服务间的独立部署与升级。


开发复杂度与生态支持

维度事件(ApplicationEvent)MQ
集成成本无需额外依赖,Spring原生支持需引入MQ客户端库、配置连接池等
学习曲线简单,仅需掌握Spring事件模型(事件类、发布者、监听器)需理解MQ协议(如AMQP)、Broker配置、消息模型等
生态工具局限于Spring生态(如@TransactionalEventListener支持多语言客户端、监控工具(如RabbitMQ Management UI)

典型用例

事件机制:订单状态变更时更新缓存。

MQ:电商系统中订单创建后向物流系统推送消息。


性能与资源消耗

吞吐量

事件机制
同步模式下受限于单线程处理能力,异步模式下性能提升但需管理线程池。

MQ
支持批量消息处理和消费者集群,吞吐量可达百万级(如Kafka)。

资源占用

事件机制:内存中传递事件对象,无网络开销。

MQ:需维护网络连接、序列化/反序列化数据,资源消耗较高。


适用场景总结

场景推荐方案理由
单体应用内的模块解耦Spring事件机制轻量级、无外部依赖,适合快速开发
分布式系统间通信MQ跨系统支持、高可靠性,适应微服务架构
事务一致性要求高的操作事件机制+事务监听器通过@TransactionalEventListener实现事务提交后触发
高并发、异步任务处理MQ利用消息堆积能力实现削峰填谷
需要历史消息追溯的场景MQ(如Kafka日志留存)支持消息持久化和回溯

混合使用策略

在实际项目中,二者可互补:
事件机制处理本地逻辑:例如在订单服务内部,使用事件更新缓存或记录日志。
MQ传递跨系统消息:订单创建后,通过MQ通知库存系统和支付系统。
事务协同:通过@TransactionalEventListener确保本地事务提交后,再向MQ发送消息,避免数据不一致。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/75291.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【复活吧,我的爱机!】Ideapad300-15isk拆机升级:加内存条 + 换固态硬盘 + 换电源

写在前面&#xff1a;本博客仅作记录学习之用&#xff0c;部分图片来自网络&#xff0c;如需引用请注明出处&#xff0c;同时如有侵犯您的权益&#xff0c;请联系删除&#xff01; 文章目录 前言升级成本升级流程电池健康度加内存条和换内存条光驱位加装机械硬盘更换电池重装系…

基于PyQt5的自动化任务管理软件:高效、智能的任务调度与执行管理

基于PyQt5的自动化任务管理软件&#xff1a;高效、智能的任务调度与执行管理 相关资源文件已经打包成EXE文件&#xff0c;可双击直接运行程序&#xff0c;且文章末尾已附上相关源码&#xff0c;以供大家学习交流&#xff0c;博主主页还有更多Python相关程序案例&#xff0c;秉着…

【区块链安全 | 第十四篇】类型之值类型(一)

文章目录 值类型布尔值整数运算符取模运算指数运算 定点数地址&#xff08;Address&#xff09;类型转换地址成员balance 和 transfersendcall&#xff0c;delegatecall 和 staticcallcode 和 codehash 合约类型&#xff08;Contract Types&#xff09;固定大小字节数组&#x…

Windows 系统下多功能免费 PDF 编辑工具详解

IceCream PDF Editor是一款极为实用且操作简便的PDF文件编辑工具&#xff0c;它完美适配Windows操作系统。其用户界面设计得十分直观&#xff0c;哪怕是初次接触的用户也能快速上手。更为重要的是&#xff0c;该软件具备丰富多样的强大功能&#xff0c;能全方位满足各类PDF编辑…

【算法day28】解数独——编写一个程序,通过填充空格来解决数独问题

37. 解数独 编写一个程序&#xff0c;通过填充空格来解决数独问题。 数独的解法需 遵循如下规则&#xff1a; 数字 1-9 在每一行只能出现一次。 数字 1-9 在每一列只能出现一次。 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。&#xff08;请参考示例图&#xff…

力扣刷题-热题100题-第29题(c++、python)

19. 删除链表的倒数第 N 个结点 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/remove-nth-node-from-end-of-list/description/?envTypestudy-plan-v2&envIdtop-100-liked 计算链表长度 对于链表&#xff0c;难的就是不知道有多少元素&#xff…

【QT】QT的多界面跳转以及界面之间传递参数

QT的多界面跳转以及界面之间传递参数 一、在QT工程中添加新的界面二、多界面跳转的两种情况1、A界面跳到B界面&#xff0c;不需要返回2、A界面跳到B界面&#xff0c;需要返回1&#xff09;使用this指针传递将当前界面地址传递给下一界面2&#xff09;使用parentWidget函数获取上…

【力扣hot100题】(022)反转链表

非常经典&#xff0c;我写的比较复杂&#xff0c;一直以来的思路都是这样&#xff0c;就没有去找更简单的解法&#xff1a;&#xff08;做链表题习惯加头结点的前置节点了&#xff0c;去掉也行&#xff09; /*** Definition for singly-linked list.* struct ListNode {* …

剑指Offer(数据结构与算法面试题精讲)C++版——day2

剑指Offer(数据结构与算法面试题精讲)C++版——day2 题目一:只出现一次的数据题目二:单词长度的最大乘积题目三:排序数组中的两个数字之和题目一:只出现一次的数据 一种很简单的思路是,使用数组存储出现过的元素,比如如果0出现过,那么arr[0]=1,但是有个问题,题目中没…

技术回顾day2

1.获取文件列表 流程&#xff1a;前端根据查询条件封装查询信息&#xff0c;后端接收后进行封装&#xff0c;封装为FileInfoQuery,根据fileInfoQuery使用mybatis的动态sql来进行查询。 2.文件分片上传 每次上传需要上传包括(文件名字&#xff0c;文件&#xff0c;md5值&#…

DeepSeek-R1 模型现已在亚马逊云科技上提供

2025年3月10日更新—DeepSeek-R1现已作为完全托管的无服务器模型在Amazon Bedrock上提供。 2025年2月5日更新—DeepSeek-R1 Distill Llama 和 Qwen模型现已在Amazon Bedrock Marketplace和Amazon SageMaker JumpStart中提供。 在最近的Amazon re:Invent大会上&#xff0c;亚马…

STP --- 生成树协议

协议信息 配置 BPDU Protocol identifier&#xff1a;协议标识 Version&#xff1a;协议版本&#xff1a;STP 为 0&#xff0c;RSTP 为 2&#xff0c;MSTP 为 3 type&#xff1a; BPDU 类型 Flag&#xff1a; 标志位 Root ID&#xff1a; 根桥 ID&#xff0c;由两字节的优…

Ansible playbook-ansible剧本

一.playbook介绍 便于功能的重复使用 本质上就是文本文件&#xff0c;一般都是以.yml结尾的文本文件。 1.遵循YAML语法 1.要求同级别代码要有相同缩进&#xff0c;建议4个空格。【同级别代码是同一逻辑的代码】 在计算机看来空格和Tob键是两个不同的字符。 2.一个键对应一…

python的基础入门

初识Python 什么是Python Python是1门程序设计语言。在开发者眼里&#xff0c;语言可以分为3类&#xff1a; 自然语言&#xff1a;人能听懂的语言&#xff0c;例如汉语&#xff0c;英语&#xff0c;法语等等。机器语言&#xff1a;机器能听懂的语言&#xff0c;机器只能听懂0…

8.neo4j图数据库python操作

使用图数据库的原因 图数据库使用neo4j的原因&#xff1a;neo4j使用率高&#xff0c;模板好找&#xff0c;报错能查。 红楼梦人物关系图地址 GraphNavigator neo4j学习手册 https://www.w3cschool.cn/neo4j/neo4j_need_for_graph_databses.html CQL代表的是Cypher查询语言…

[Lc6_记忆化搜索] 扫雷游戏 | 理解 递归vs记忆化搜索vs dp

目录 ⭕1.扫雷游戏 题解 1.记忆化搜索 解法一&#xff1a;递归 解法二&#xff1a;记忆化搜索 解法三&#xff1a;动态规划 ⭕1.扫雷游戏 (暴力模拟&#xff09; 链接&#xff1a;529. 扫雷游戏 让我们一起来玩扫雷游戏&#xff01; 给你一个大小为 m x n 二维字符矩阵…

第十一章:Python PIL库-图像处理

一、PIL库简介 PIL&#xff08;Python Imaging Library&#xff09;是一个功能强大的图像处理库&#xff0c;它提供了丰富的图像处理功能&#xff0c;包括图像的打开、处理和保存等操作。PIL支持多种图像文件格式&#xff0c;如JPEG、PNG、BMP等&#xff0c;并且可以完成对图像…

ISIS报文

IS-IS 报文 目录 IS-IS 报文 一、报文类型与功能 二、报文结构解析 三、核心功能特性 四、典型应用场景 五、抓包数据分析 六、总结 IS-IS&#xff08;中间系统到中间系统&#xff09;协议报文是用于链路状态路由协议中网络设备间交换路由信息的关键载体&#xff0c;其设…

beikeshop多商户跨境电商独立站最新版v1.6.0版本源码

一.介绍 beikeshop跨境电商独立站最新版V1.6.0源码 多商户 多商家 多语言 多币结算 本博主亲测搭建代码全开源质量相对来说很稳定的 二.服务器环境 系统&#xff1a;CentOS、 环境&#xff1a;PHP7.4 Nginx 1.21 MySQL 5.6 常见插件&#xff1a;fileinfo &#xff1b; re…

Spring Boot 集成实战:AI 工具如何自动生成完整微服务模块

在数字化转型的浪潮中&#xff0c;开发效率和质量是企业竞争力的关键要素。飞算 JavaAI 作为一款创新的 AI 工具&#xff0c;能在 Spring Boot 开发中&#xff0c;自动生成完整微服务模块&#xff0c;极大提升开发效率。下面&#xff0c;我们就详细介绍如何借助飞算 JavaAI&…