最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JAVA | Guava EventBus 使用 發(fā)布/訂閱模式的步驟

 更新時間:2021年03月02日 10:25:08   作者:雙鬼帶單  
這篇文章主要介紹了JAVA | Guava EventBus 使用 發(fā)布/訂閱模式的步驟,幫助大家更好的理解和學習使用Guava EventBus,感興趣的朋友可以了解下

前言

EventBus 是 Guava 的事件處理機制,是觀察者模式(生產/消費模型)的一種實現(xiàn)。

觀察者模式在我們日常開發(fā)中使用非常廣泛,例如在訂單系統(tǒng)中,訂單狀態(tài)或者物流信息的變更會向用戶發(fā)送APP推送、短信、通知賣家、買家等等;審批系統(tǒng)中,審批單的流程流轉會通知發(fā)起審批用戶、審批的領導等等。

Observer模式也是 JDK 中自帶就支持的,其在 1.0 版本就已經存在 Observer,不過隨著 Java 版本的飛速升級,其使用方式一直沒有變化,許多程序庫提供了更加簡單的實現(xiàn),例如 Guava EventBus、RxJava、EventBus 等

一、為什么要用 Observer模式以及 EventBus 優(yōu)點 ?

EventBus 優(yōu)點

  • 相比 Observer 編程簡單方便
  • 通過自定義參數可實現(xiàn)同步、異步操作以及異常處理
  • 單進程使用,無網絡影響

缺點

  • 只能單進程使用
  • 項目異常重啟或者退出不保證消息持久化

如果需要分布式使用還是需要使用 MQ

二、EventBus 使用步驟

1. 引入庫

Gradle

compile group: 'com.google.guava', name: 'guava', version: '29.0-jre'

Maven

<dependency>
  <groupId>com.google.guava</groupId>
  <artifactId>guava</artifactId>
  <version>29.0-jre</version>
</dependency>

引入依賴后,這里我們主要使用 com.google.common.eventbus.EventBus 類進行操作,其提供了 registerunregister、post 來進行注冊訂閱、取消訂閱和發(fā)布消息

public void register(Object object);

public void unregister(Object object);

public void post(Object event);

2. 同步使用

1. 首先創(chuàng)建一個 EventBus

EventBus eventBus = new EventBus();

2. 創(chuàng)建一個訂閱者

在 Guava EventBus 中,是根據參數類型進行訂閱,每個訂閱的方法只能由一個參數,同時需要使用 @Subscribe 標識

class EventListener {

 /**
  * 監(jiān)聽 Integer 類型的消息
  */
 @Subscribe
 public void listenInteger(Integer param) {
  System.out.println("EventListener#listenInteger ->" + param);
 }

 /**
  * 監(jiān)聽 String 類型的消息
  */
 @Subscribe
 public void listenString(String param) {
  System.out.println("EventListener#listenString ->" + param);
 }
}

3. 注冊到 EventBus 上并發(fā)布消息

EventBus eventBus = new EventBus();

eventBus.register(new EventListener());

eventBus.post(1);
eventBus.post(2);
eventBus.post("3");

運行結果為

EventListener#listenInteger ->1
EventListener#listenInteger ->2
EventListener#listenString ->3

根據需要我們可以創(chuàng)建多個訂閱者完成訂閱信息,同時如果一個類型存在多個訂閱者,則所有訂閱方法都會執(zhí)行

為什么說這么做是同步的呢?

Guava Event 實際上是使用線程池來處理訂閱消息的,通過源碼可以看出,當我們使用默認的構造方法創(chuàng)建 EventBus 的時候,其中 executorMoreExecutors.directExecutor(),其具體實現(xiàn)中直接調用的 Runnable#run 方法,使其仍然在同一個線程中執(zhí)行,所以默認操作仍然是同步的,這種處理方法也有適用的地方,這樣既可以解耦也可以讓方法在同一個線程中執(zhí)行獲取同線程中的便利,比如事務的處理

EventBus 部分源碼

public class EventBus {
 private static final Logger logger = Logger.getLogger(EventBus.class.getName());
 private final String identifier;
 private final Executor executor;
 private final SubscriberExceptionHandler exceptionHandler;
 private final SubscriberRegistry subscribers;
 private final Dispatcher dispatcher;

 public EventBus() {
  this("default");
 }

 public EventBus(String identifier) {
  this(identifier, MoreExecutors.directExecutor(), Dispatcher.perThreadDispatchQueue(), EventBus.LoggingHandler.INSTANCE);
 }

 public EventBus(SubscriberExceptionHandler exceptionHandler) {
  this("default", MoreExecutors.directExecutor(), Dispatcher.perThreadDispatchQueue(), exceptionHandler);
 }

 EventBus(String identifier, Executor executor, Dispatcher dispatcher, SubscriberExceptionHandler exceptionHandler) {
  this.subscribers = new SubscriberRegistry(this);
  this.identifier = (String)Preconditions.checkNotNull(identifier);
  this.executor = (Executor)Preconditions.checkNotNull(executor);
  this.dispatcher = (Dispatcher)Preconditions.checkNotNull(dispatcher);
  this.exceptionHandler = (SubscriberExceptionHandler)Preconditions.checkNotNull(exceptionHandler);
 }
}

DirectExecutor 部分源碼

enum DirectExecutor implements Executor {
 INSTANCE;

 private DirectExecutor() {
 }

 public void execute(Runnable command) {
  command.run();
 }

 public String toString() {
  return "MoreExecutors.directExecutor()";
 }
}

3. 異步使用

通過上面的源碼,可以看出只要將構造方法中的 executor 換成一個線程池實現(xiàn)即可, 同時 Guava EventBus 為了簡化操作,提供了一個簡化的方案即 AsyncEventBus

EventBus eventBus = new AsyncEventBus(Executors.newCachedThreadPool());

這樣即可實現(xiàn)異步使用

AsyncEventBus 源碼

public class AsyncEventBus extends EventBus {
 public AsyncEventBus(String identifier, Executor executor) {
  super(identifier, executor, Dispatcher.legacyAsync(), LoggingHandler.INSTANCE);
 }

 public AsyncEventBus(Executor executor, SubscriberExceptionHandler subscriberExceptionHandler) {
  super("default", executor, Dispatcher.legacyAsync(), subscriberExceptionHandler);
 }

 public AsyncEventBus(Executor executor) {
  super("default", executor, Dispatcher.legacyAsync(), LoggingHandler.INSTANCE);
 }
}

4. 異常處理

如果處理時發(fā)生異常應該如何處理? 在看源碼中,無論是 EventBus 還是 AsyncEventBus 都可傳入自定義的 SubscriberExceptionHandler 該 handler 當出現(xiàn)異常時會被調用,我可可以從參數 exception 獲取異常信息,從 context 中獲取消息信息進行特定的處理

其接口聲明為

public interface SubscriberExceptionHandler {
 /** Handles exceptions thrown by subscribers. */
 void handleException(Throwable exception, SubscriberExceptionContext context);
}

總結

在上面的基礎上,我們可以定義一些消息類型來實現(xiàn)不同消息的監(jiān)聽和處理,通過實現(xiàn) SubscriberExceptionHandler 來處理異常的情況,無論時同步還是異步都能游刃有余

參考

https://github.com/google/guava
https://github.com/greenrobot/EventBus
https://github.com/ReactiveX/RxJava

以上就是JAVA | Guava EventBus 使用 發(fā)布/訂閱模式的步驟的詳細內容,更多關于Guava EventBus 使用 發(fā)布/訂閱模式的資料請關注腳本之家其它相關文章!

您可能感興趣的文章:

相關文章

  • java多線程實現(xiàn)文件下載

    java多線程實現(xiàn)文件下載

    這篇文章主要為大家詳細介紹了java多線程實現(xiàn)文件下載,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-07-07
  • idea指定啟動參數、環(huán)境變量的過程

    idea指定啟動參數、環(huán)境變量的過程

    這篇文章主要介紹了idea指定啟動參數、環(huán)境變量的操作過程,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-07-07
  • Spring?Data?Exists查詢最佳方法編寫示例

    Spring?Data?Exists查詢最佳方法編寫示例

    這篇文章主要為大家介紹了Spring?Data?Exists查詢最佳方法編寫示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • Java使用正則表達式提取XML節(jié)點內容的方法示例

    Java使用正則表達式提取XML節(jié)點內容的方法示例

    這篇文章主要介紹了Java使用正則表達式提取XML節(jié)點內容的方法,結合具體實例形式分析了java針對xml格式字符串的正則匹配相關操作技巧,需要的朋友可以參考下
    2017-08-08
  • Java?設計模式中的策略模式詳情

    Java?設計模式中的策略模式詳情

    這篇文章主要介紹了Java?設計模式中的策略模式詳情,文章圍繞主題展開詳細的內容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-09-09
  • SpringBoot項目集成xxljob實現(xiàn)全紀錄

    SpringBoot項目集成xxljob實現(xiàn)全紀錄

    XXL-JOB是一個分布式任務調度平臺,本文主要介紹了SpringBoot項目集成xxljob實現(xiàn)全紀錄,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • Java?枚舉的常用技巧匯總

    Java?枚舉的常用技巧匯總

    在Java中,枚舉類型是一種特殊的數據類型,允許定義一組固定的常量,默認情況下,toString方法返回枚舉常量的名稱,本文提供了一個完整的代碼示例,展示了如何在Java中通過重寫枚舉的toString方法來展示枚舉實例的字段信息,感興趣的朋友一起看看吧
    2025-01-01
  • Java String類簡單用法實戰(zhàn)示例【字符串輸出、比較】

    Java String類簡單用法實戰(zhàn)示例【字符串輸出、比較】

    這篇文章主要介紹了Java String類簡單用法,結合具體實例形式分析了Java使用String類實現(xiàn)字符串的輸出和比較功能相關操作技巧,需要的朋友可以參考下
    2019-07-07
  • 基于rabbitmq延遲插件實現(xiàn)分布式延遲任務

    基于rabbitmq延遲插件實現(xiàn)分布式延遲任務

    這篇文章主要介紹了基于rabbitmq延遲插件實現(xiàn)分布式延遲任務,今天我們講解延遲隊列的實現(xiàn)方式,而延遲隊列有很多種實現(xiàn)方式,今天就每種實現(xiàn)方式給大家大概介紹下,感興趣的朋友一起看看吧
    2022-01-01
  • 如何將JSP/Servlet項目轉換為Spring Boot項目

    如何將JSP/Servlet項目轉換為Spring Boot項目

    這篇文章主要介紹了如何將JSP/Servlet項目轉換為Spring Boot項目,幫助大家更好的利用springboot進行網絡編程,感興趣的朋友可以了解下
    2020-10-10

最新評論

运城市| 阜康市| 通城县| 牡丹江市| 普宁市| 勐海县| 湛江市| 青川县| 洞头县| 和田县| 南丰县| 通渭县| 岫岩| 平乐县| 枣阳市| 苏州市| 镇康县| 徐汇区| 博白县| 同仁县| 长汀县| 锦屏县| 彰武县| 赣州市| 云龙县| 涞源县| 株洲市| 安宁市| 区。| 常德市| 保山市| 维西| 沁源县| 永春县| 湄潭县| 高雄市| 奈曼旗| 古田县| 九江市| 义乌市| 庆元县|