EventBus是Guava封裝的事件處理機制,屬于設計模式中的觀察者模式(生產|消費者編程模型)。使用簡單、優雅只關注業務本身,僅限JVM內部使用,缺點:不適用分布式,看實際業務可選用MQ。
事件總線(EventBus)處理個服務、或業務間公共線路,而EventBus則是存儲事件、處理時間中間服務,通過post()往EventBus發送事件,由EventBus去調度對應訂閱方(subscriber)消費處理,解耦觀察者模式中訂閱方與事件源之間強依賴關系。
(相關資料圖)
com.google.guava guava20.0 復制代碼場景舉例(偽代碼) public class EventBusCenter { private static EventBus eventBus = new EventBus(); private EventBusCenter() { } public static EventBus getInstance(){ return eventBus; } /**注冊監聽*/ public static void register(Object listener){ eventBus.register(listener); } /**取消注冊*/ public static void unregister(Object listener){ eventBus.unregister(listener); } /**發布事件*/ public static void post(Object event){ eventBus.post(event); }}復制代碼定義業務對象
public class OrderInfo { private long orderId; private String orderName; } public class OrderFailInfo{ private long orderId; private String orderName; private String msg;}復制代碼支付成功監聽處理事件
public class OrderSuccessListener { @Subscribe public void orderSubscribe(OrderInfo event) { // 訂單業務監聽 System.out.println("訂單支付成功處理事件: " + event); } @Subscribe public void ortherSubscribe(OrderInfo event) { // 其它業務監聽 System.out.println("訂單支付成功其它處理事件: " + event); }}復制代碼支付失敗監聽處理事件
public class OrderFailListener { @Subscribe public void orderSubscribe(OrderFailInfo event) { // 訂單業務監聽 System.err.println("訂單支付失敗處理事件: " + event); } @Subscribe public void ortherSubscribe(String event) { // 其它業務監聽 System.err.println("訂單支付失敗其它處理事件: " + event); }}復制代碼測試
public class EventBusTest { public static void main(String[] args) { OrderSuccessListener successListener = new OrderSuccessListener(); OrderFailListener failListener = new OrderFailListener(); EventBusCenter.register(successListener); EventBusCenter.register(failListener); OrderInfo order = OrderInfo.builder().orderId(111L).orderName("訂單名稱xxx").build(); log.info("=====支付成功======="); EventBusCenter.post(order); log.info("=====支付失敗======="); OrderFailInfo orderFail = OrderFailInfo.builder().orderId(111L).orderName("訂單名稱xxx").msg("支付失敗").build(); EventBusCenter.post(orderFail); log.info("=====記錄支付失敗原因======="); EventBusCenter.post("用戶取消訂單"); }}輸出結果:信息: =====支付成功=======訂單支付成功其它處理事件: OrderInfo(orderId=111, orderName=訂單名稱xxx)訂單支付成功處理事件: OrderInfo(orderId=111, orderName=訂單名稱xxx)信息: =====支付失敗=======訂單支付失敗處理事件: OrderFailInfo(orderId=111, orderName=訂單名稱xxx, msg=支付失敗)信息: =====記錄支付失敗原因=======訂單支付失敗其它處理事件: 用戶取消訂單復制代碼使用說明:
只有通過***@Subscribe***注解才會被注冊進EventBus 監聽方法只能有1個參數,當有多個監聽方法時,參數類型一樣并行消費;不同參類型對應不對消費事件初始化EvenBus
EventBus(String identifier, Executor executor, Dispatcher dispatcher, SubscriberExceptionHandler exceptionHandler) { this.subscribers = new SubscriberRegistry(this);//所有觀察者列表維護對象 this.identifier = (String) Preconditions.checkNotNull(identifier);// EventBus的處理標識符(方法名稱) //executor是事件分發過程中使用到的線程池,可以自己實現 this.executor = (Executor)Preconditions.checkNotNull(executor); //Dispatcher類型的子類,對監聽者分發策略,主要有3種方式 this.dispatcher = (Dispatcher)Preconditions.checkNotNull(dispatcher); //異常處理策咯 this.exceptionHandler = (SubscriberExceptionHandler)Preconditions.checkNotNull(exceptionHandler); }復制代碼注冊監聽–>register()
作用:初始化監聽者類型與監聽方法的集合 subscribers ,在 發布事件 場景由傳入參數類型,匹配、并執行對應監聽者方法
①獲取指定監聽者對應的全部觀察者集合(一對多)
②獲取對應**@Subscribe**觀察者事件類型(即:方法參數類型)集合
③添加對應類型所有觀察者到集合事件集合中(即:SubscriberRegistry對象維護的 subscribers 集合)
subscribers說明:
private final ConcurrentMap, CopyOnWriteArraySet>subscribers = Maps.newConcurrentMap();復制代碼 防止并發問題維護一個ConcurrentMap集合,Subscriber集合對應velue使用的是Java中的CopyOnWriteArraySet集合,
主要作用:1、避免監聽重復事件 2、適用于讀多寫少的場景:只要register()才寫入,基本都是查詢
findAllSubscribers()說明
①獲取注冊監聽對象所有包含**@Subscribe**的方法(如下圖所示??)
②通過反射獲取對應方法、及監聽參數類型
③放入當前初始化的EventBus對象里面,維護監聽對象與監聽方法的對應關系
首先從 subscriberMethodsCache 緩存中獲取監聽對象映射關系,如果緩存中不存在通過反射遍歷所有包含**@Subscribe**的方法
發布事件–>post()
①getSubscribers()方法獲取該事件對應的全部觀察者
②Dispatcher-分發事件策略
ImmediateDispatcher:直接在當前線程中遍歷所有的觀察者并進行事件分發
LegacyAsyncDispatcher:使用 全局隊列 ,先將觀察者依次放入隊列,再順序從隊列中取出觀察者對象進行事件分發
PerThreadQueuedDispatcher(默認):使用 線程相關隊列 ,會先獲取當前線程的觀察者隊列,并將傳入的觀察者列表傳入到該隊列中;判斷當前線程是否正在進行分發操作,如果沒有在進行分發操作,就通過遍歷上述隊列進行事件分發
最后無論使用哪個分發器,都會執行dispatchEvent()方法,通過反射(target、method、executor)多線程觸發監聽方法
原文鏈接:https://juejin.cn/post/7224310314807083065
上一篇:焦點快播:2019年第三季度是哪幾個月-第三季度是哪幾個月
下一篇:最后一頁