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.pswp.cn/bicheng/75291.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/75291.shtml
英文地址,請注明出處:http://en.pswp.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;秉著…

JavaScript 庫:全面解析與推薦

JavaScript 庫:全面解析與推薦 引言 JavaScript 作為當今最流行的前端開發語言之一,擁有豐富的庫和框架。這些庫和框架極大地簡化了開發工作,提高了開發效率。本文將全面解析 JavaScript 庫,并推薦一些優秀的庫,幫助開發者更好地掌握 JavaScript。 JavaScript 庫概述 …

C#從入門到精通(5)

目錄 第十二章 其他基礎知識 &#xff08;1&#xff09;抽象類和方法 &#xff08;2&#xff09;接口 &#xff08;3&#xff09;集合與索引器 &#xff08;4&#xff09;委托和匿名方法 &#xff08;5&#xff09;事件 &#xff08;6&#xff09;迭代器 &#xff08;7…

【區塊鏈安全 | 第十四篇】類型之值類型(一)

文章目錄 值類型布爾值整數運算符取模運算指數運算 定點數地址&#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編輯…

vue3相比于vue2的提升

性能提升&#xff1a; Vue3的頁面渲染速度更快、性能更好。特別是在處理大量數據和復雜組件時&#xff0c;優勢更加明顯。Vue3引入了編譯時優化&#xff0c;如靜態節點提升&#xff08;hoistStatic&#xff09;、補丁標志&#xff08;patchflag&#xff09;等&#xff0c;這些…

Redis 梳理匯總目錄

Redis 哨兵集群&#xff08;Sentinel&#xff09;與 Cluster 集群對比-CSDN博客 如何快速將大規模數據保存到Redis集群-CSDN博客 Redis的一些高級指令-CSDN博客 Redis 篇-CSDN博客

【奇點時刻】GPT-4o新生圖特性深度洞察報告

以下報告圍繞最新推出的「GPT4o」最新圖像生成技術展開&#xff0c;旨在讓讀者從整體層面快速了解其技術原理、功能亮點&#xff0c;以及與其他常見圖像生成或AI工具的對比分析&#xff0c;同時也會客觀探討該技術在應用過程中可能遇到的挑戰與限制。 1. 技術背景概述 GPT4o新…

【算法day28】解數獨——編寫一個程序,通過填充空格來解決數獨問題

37. 解數獨 編寫一個程序&#xff0c;通過填充空格來解決數獨問題。 數獨的解法需 遵循如下規則&#xff1a; 數字 1-9 在每一行只能出現一次。 數字 1-9 在每一列只能出現一次。 數字 1-9 在每一個以粗實線分隔的 3x3 宮內只能出現一次。&#xff08;請參考示例圖&#xff…

【已解決】Javascript setMonth跨月問題;2025-03-31 setMonth后變成 2025-05-01

文章目錄 bug重現解決方法&#xff1a;用第三方插件來實現&#xff08;不推薦原生代碼來實現&#xff09;。項目中用的有dayjs。若要自己實現&#xff0c;參考 AI給出方案&#xff1a; bug重現 今天&#xff08;2025-04-01&#xff09;遇到的一個問題。原代碼邏輯大概是這樣的…

力扣刷題-熱題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,但是有個問題,題目中沒…

【C++游戲引擎開發】《線性代數》(3):矩陣乘法的SIMD優化與轉置加速

一、矩陣乘法數學原理與性能瓶頸 1.1 數學原理 矩陣乘法定義為:給定兩個矩陣 A ( m n ) \mathrm{A}(mn) A(mn)和 B ( n p ) \mathrm{B}(np) B(np),它們的乘積 C = A B \mathrm{C}=AB C=AB 是一個 m p \mathrm{m}p mp 的矩陣,其中: C i , j = ∑ k = 1…

Vue Transition組件類名+TailwindCSS

#本文教學結合TailwindCSS實現一個Transition動畫的例子# 舉例代碼&#xff1a; <transition enter-active-class"transition-all duration-300 ease-out"enter-from-class"opacity-0 translate-y-[-10px]"enter-to-class"opacity-100 translate-…

技術回顧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;由兩字節的優…