詳解Guava中EventBus的使用
Guava EventBus
EventBus是Guava的事件處理機(jī)制,是設(shè)計模式中觀察者模式(生產(chǎn)/消費者編程模型)的優(yōu)雅實現(xiàn)。對于事件監(jiān)聽和發(fā)布訂閱模式,EventBus使用非常簡單便捷。
如果你做過CS的開發(fā),下面這段代碼可能會比較熟悉。
Button?button?=?new?Button("確定"); button.addListener(?new?Listener(){ ????... ????public?void?onClick(Event?event){ ????????//? ????} ????... }?);
為按鈕注冊事件監(jiān)聽,當(dāng)按鈕被點擊時,則觸發(fā)監(jiān)聽中相應(yīng)的回調(diào)。在上面的代碼中,有三個角色事件(Event),事件源(Button),監(jiān)聽(Listener),按鈕作為事件源,當(dāng)點擊行為觸發(fā)時,會將該行為封裝成對應(yīng)的點擊事件,并根據(jù)行為類型將事件傳遞到響應(yīng)的監(jiān)聽器上, 這也就是我們常說的監(jiān)聽器模式。
使用場景
實現(xiàn)消息生產(chǎn)者與消費者間的解耦,對應(yīng)事件源與監(jiān)聽器,而消息則是事件
通過事件驅(qū)動業(yè)務(wù)流程扭轉(zhuǎn),通過異步執(zhí)行機(jī)制實現(xiàn)代碼非阻塞執(zhí)行
擴(kuò)展主線外的分支業(yè)務(wù),減少代碼的侵入,比如各個環(huán)節(jié)的消息通知、短信提醒等
實現(xiàn)消息廣播到不同的模塊中
示例
訂單支付時的消息發(fā)送
//?商品 public?class?ProductOrder?{ ????private?String?user;?//?用戶 ????private?String?product;?//?商品 ????private?double?amount;?//?金額 ????@Override ????public?String?toString()?{ ????????return?String.format("用戶:%s購買了商品:%s,總金額:%s",?user,?product,?amount); ????} } //?事件 ????@Data ????@AllArgsConstructor ????public?static?class?CreateOrderEvent?implements?OrderEvent{ ????????private?ProductOrder?order; ????} //?監(jiān)聽 ????public?static?class?CreateOrderListener{ ????????@Subscribe ????????public?void?onEvent(CreateOrderEvent?event)?{ ????????????log.info("創(chuàng)建訂單:{}",?event.getOrder()); ????????} ????}
測試: 我們可以定義各種事件,比如訂單創(chuàng)建、訂單取消、訂單支付... 只需要簡單的三個步驟即可:
//?1.?創(chuàng)建事件總線 ????EventBus?eventBus?=?new?EventBus(?ProductOrder.class.getName()?); //?2.?注冊事件監(jiān)聽 ????eventBus.register(?new?CreateOrderListener()?); ????eventBus.register(?new?PayOrderListener()?); ????eventBus.register(?new?CancelOrderListener()?); ????eventBus.register(?new?RenewOrderListener()?); //?3.?發(fā)送事件通知 ????eventBus.post(new?ProductOrder.CreateOrderEvent(order)); ????TimeUnit.SECONDS.sleep(1); ????eventBus.post(new?ProductOrder.CancelOrderEvent(order)); ????TimeUnit.SECONDS.sleep(1); ????eventBus.post(new?ProductOrder.RenewOrderEvent(order)); ????TimeUnit.SECONDS.sleep(1); ????eventBus.post(new?ProductOrder.PayOrderEvent(order)); ????TimeUnit.SECONDS.sleep(5); ????eventBus.post(new?ProductOrder.ReturnOrderEvent(order));
同時我們可以通過AsyncEventBus建立事件異步總線,這樣在事件被觸發(fā)時,可以異步通知監(jiān)聽者完成事件回調(diào),以此來提高響應(yīng)速度。
核心
EventBus
事件總線,可以理解為事件與監(jiān)聽器的上下文,主要實現(xiàn)事件的注冊、事件的分發(fā)、以及監(jiān)聽器的回調(diào),主要提供的方法包括:
- register 注冊監(jiān)聽,將監(jiān)聽器注冊到事件總線,通過注解@Subscribe通知其監(jiān)聽的事件類型(第一個方法參數(shù)類型)
- unregister 卸載監(jiān)聽,從事件總線移除監(jiān)聽
- post 發(fā)送事件通知,根據(jù)post事件類型,找到所有訂閱了該類型事件的監(jiān)聽器,并將事件推送到監(jiān)聽器對應(yīng)的監(jiān)聽方法
Subscribe
通過@Subscribe標(biāo)識監(jiān)聽器所關(guān)注的事件類型
Event
可以是任何對象,當(dāng)然不建議將基礎(chǔ)類型或String作為事件類型,這樣就沒法做到按類型區(qū)分了
通過上面的圖就可以很清楚各個各個組件的職責(zé),以及如何通過事件總線完成事件向監(jiān)聽的傳播,最終基于事件回調(diào)機(jī)制完成消息傳遞?;谑录?qū)動的服務(wù)模型
上面這種結(jié)構(gòu)的圖形是不是在很多位置都見過,這是一種經(jīng)典的設(shè)計模式。試想一下,我們不通過事件驅(qū)動行為時,一般你們怎么寫代碼,通過ifelse?或者其他有著異曲同工的 實現(xiàn)方法,目的最后都是一樣?;贕uava提供的工具,我們不僅在使用時只需要簡單的三個步驟就能實現(xiàn),同樣,當(dāng)需要屏蔽該功能時只需要去掉register一行即可,對整體功能 也沒有任何的影響。
在我們引入某種設(shè)計模式,某種架構(gòu)模型時,總的目的都是為了降低代碼模塊間的耦合度,提升代碼整體的可讀性,最終讓代碼能夠易于維護(hù)性,或者有一定的復(fù)用性。
總結(jié)
事件監(jiān)聽模式、觀察者模式、發(fā)布訂閱模式,都是非常的相似,通過建立事件與監(jiān)聽器、觀察者與被觀察者、生產(chǎn)者與消費者者間消息傳遞媒介(示例中的事件總線EventBus),
不僅能夠使消息的發(fā)起者與接收者之間進(jìn)行解耦,最主要的是通過消息傳遞渠道實現(xiàn)消息異步傳播,提升系統(tǒng)效率
到此這篇關(guān)于詳解Guava中EventBus的使用的文章就介紹到這了,更多相關(guān)Guava EventBus內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
IDEA使用Gradle構(gòu)建SpringBoot項目工程的詳細(xì)教程
這篇文章主要介紹了IDEA使用Gradle構(gòu)建SpringBoot項目工程的教程詳解,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-08-08SpringBoot超詳細(xì)講解集成Flink的部署與打包方法
昨天折騰了下SpringBoot與Flink集成,實際上集成特簡單,主要是部署打包的問題折騰了不少時間。想打出的包直接可以java -jar運(yùn)行,同時也可以flink run運(yùn)行,或者在flink的dashboard上上傳點擊啟動。結(jié)果是不行,但是使用不同的插件打包還是可以的2022-05-05Java在排序數(shù)組中查找元素的第一個和最后一個位置的方法詳解
相信大家在操作Java的時候經(jīng)常會要在一個數(shù)組(無序)中查找元素的第一個和最后一個位置,下面這篇文章主要給大家介紹了關(guān)于Java在排序數(shù)組中查找元素的第一個和最后一個位置的相關(guān)資料,需要的朋友可以參考下2024-01-01Java 數(shù)據(jù)結(jié)構(gòu)與算法系列精講之字符串暴力匹配
字符串暴力匹配算法是指在一個長字符串中暴力尋找是否包含某一子串所謂暴力匹配,就是不使用任何其他算法,將兩個字符串中的字符一一進(jìn)行比對2022-02-02xxl-job定時任務(wù)配置應(yīng)用及添加到springboot項目中實現(xiàn)動態(tài)API調(diào)用
XXL-JOB是一個分布式任務(wù)調(diào)度平臺,其核心設(shè)計目標(biāo)是開發(fā)迅速、學(xué)習(xí)簡單、輕量級、易擴(kuò)展,本篇文章主要是對xuxueli的xxl-job做一個簡單的配置,以及將其添加到自己已有的項目中進(jìn)行api調(diào)用,感興趣的朋友跟隨小編一起看看吧2024-04-04Spring Boot @Async 異步任務(wù)執(zhí)行方法
本篇文章主要介紹了Spring Boot @Async 異步任務(wù)執(zhí)行方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-05-05Spring?Cloud?Alibaba實現(xiàn)服務(wù)的無損下線功能(案例講解)
這篇文章主要介紹了Spring?Cloud?Alibaba實現(xiàn)服務(wù)的無損下線功能?,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-03-03SpringBoot整合Swagger接口文檔工具的流程步驟
我們在開發(fā)接口的時候,會將接口文檔給前端的開發(fā)者進(jìn)行對接,我們可以通過Postman或者Yapi等接口管理工具進(jìn)行編寫管理,實際開發(fā)中,接口的管理確實也應(yīng)該通過專業(yè)的工具管理,本文,我們就來談?wù)勗趺丛赟pringBoot整合Swagger接口文檔工具2023-08-08