Guava----EventBus


參考文獻:https://www.cnblogs.com/peida/p/EventBus.html

EventBus是Guava的事件處理機制,是設計模式中的觀察者模式(生產/消費者編程模型)的優雅實現。對於事件監聽和發布訂閱模式,EventBus是一個非常優雅和簡單解決方案,我們不用創建復雜的類和接口層次結構。

  Observer模式是比較常用的設計模式之一,雖然有時候在具體代碼里,它不一定叫這個名字,比如改頭換面叫個Listener,但模式就是這個模式。手工實現一個Observer也不是多復雜的一件事,只是因為這個設計模式實在太常用了,Java就把它放到了JDK里面:Observable和Observer,從JDK 1.0里,它們就一直在那里。從某種程度上說,它簡化了Observer模式的開發,至少我們不用再手工維護自己的Observer列表了。不過,如前所述,JDK里的Observer從1.0就在那里了,直到Java 7,它都沒有什么改變,就連通知的參數還是Object類型。要知道,Java 5就已經泛型了。Java 5是一次大規模的語法調整,許多程序庫從那開始重新設計了API,使其更簡潔易用。當然,那些不做應對的程序庫,多半也就過時了。這也就是這里要討論知識更新的原因所在。今天,對於普通的應用,如果要使用Observer模式該如何做呢?答案是Guava的EventBus。

  EventBus基本用法:

  使用Guava之后, 如果要訂閱消息, 就不用再繼承指定的接口, 只需要在指定的方法上加上@Subscribe注解即可。代碼如下:

  消息封裝類:

   springboot引入依賴:

<dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>23.0</version>
        </dependency>

 

 

 

 

 

復制代碼
public class TestEvent { private final int message; public TestEvent(int message) { this.message = message; System.out.println("event message:"+message); } public int getMessage() { return message; } }
復制代碼

  消息接受類:

復制代碼
public class EventListener { public int lastMessage = 0; @Subscribe public void listen(TestEvent event) { lastMessage = event.getMessage(); System.out.println("Message:"+lastMessage); } public int getLastMessage() { return lastMessage; } }
復制代碼

  測試類及輸出結果:

復制代碼
public class TestEventBus { @Test public void testReceiveEvent() throws Exception { EventBus eventBus = new EventBus("test"); EventListener listener = new EventListener(); eventBus.register(listener); eventBus.post(new TestEvent(200)); eventBus.post(new TestEvent(300)); eventBus.post(new TestEvent(400)); System.out.println("LastMessage:"+listener.getLastMessage()); ; } } //輸出信息 event message:200 Message:200 event message:300 Message:300 event message:400 Message:400 LastMessage:400
復制代碼

   MultiListener的使用:

  只需要在要訂閱消息的方法上加上@Subscribe注解即可實現對多個消息的訂閱,代碼如下:

復制代碼
public class MultipleListener { public Integer lastInteger; public Long lastLong; @Subscribe public void listenInteger(Integer event) { lastInteger = event; System.out.println("event Integer:"+lastInteger); } @Subscribe public void listenLong(Long event) { lastLong = event; System.out.println("event Long:"+lastLong); } public Integer getLastInteger() { return lastInteger; } public Long getLastLong() { return lastLong; } }
復制代碼

  測試類:

復制代碼
public class TestMultipleEvents { @Test public void testMultipleEvents() throws Exception { EventBus eventBus = new EventBus("test"); MultipleListener multiListener = new MultipleListener(); eventBus.register(multiListener); eventBus.post(new Integer(100)); eventBus.post(new Integer(200)); eventBus.post(new Integer(300)); eventBus.post(new Long(800)); eventBus.post(new Long(800990)); eventBus.post(new Long(800882934)); System.out.println("LastInteger:"+multiListener.getLastInteger()); System.out.println("LastLong:"+multiListener.getLastLong()); } } //輸出信息 event Integer:100 event Integer:200 event Integer:300 event Long:800 event Long:800990 event Long:800882934 LastInteger:300 LastLong:800882934
復制代碼

  Dead Event:

  如果EventBus發送的消息都不是訂閱者關心的稱之為Dead Event。實例如下:

復制代碼
public class DeadEventListener { boolean notDelivered = false; @Subscribe public void listen(DeadEvent event) { notDelivered = true; } public boolean isNotDelivered() { return notDelivered; } }
復制代碼

  測試類:

復制代碼
public class TestDeadEventListeners { @Test public void testDeadEventListeners() throws Exception { EventBus eventBus = new EventBus("test"); DeadEventListener deadEventListener = new DeadEventListener(); eventBus.register(deadEventListener); eventBus.post(new TestEvent(200)); eventBus.post(new TestEvent(300)); System.out.println("deadEvent:"+deadEventListener.isNotDelivered());  } } //輸出信息 event message:200 event message:300 deadEvent:true
復制代碼

  說明:如果沒有消息訂閱者監聽消息, EventBus將發送DeadEvent消息,這時我們可以通過log的方式來記錄這種狀態。

  Event的繼承:

  如果Listener A監聽Event A, 而Event A有一個子類Event B, 此時Listener A將同時接收Event A和B消息,實例如下:

  Listener 類:

復制代碼
public class NumberListener { private Number lastMessage; @Subscribe public void listen(Number integer) { lastMessage = integer; System.out.println("Message:"+lastMessage); } public Number getLastMessage() { return lastMessage; } } public class IntegerListener { private Integer lastMessage; @Subscribe public void listen(Integer integer) { lastMessage = integer; System.out.println("Message:"+lastMessage); } public Integer getLastMessage() { return lastMessage; } } 
復制代碼

  測試類:

復制代碼
public class TestEventsFromSubclass { @Test public void testEventsFromSubclass() throws Exception { EventBus eventBus = new EventBus("test"); IntegerListener integerListener = new IntegerListener(); NumberListener numberListener = new NumberListener(); eventBus.register(integerListener); eventBus.register(numberListener); eventBus.post(new Integer(100)); System.out.println("integerListener message:"+integerListener.getLastMessage()); System.out.println("numberListener message:"+numberListener.getLastMessage()); eventBus.post(new Long(200L)); System.out.println("integerListener message:"+integerListener.getLastMessage()); System.out.println("numberListener message:"+numberListener.getLastMessage()); } } //輸出類 Message:100 Message:100 integerListener message:100 numberListener message:100 Message:200 integerListener message:100 numberListener message:200
復制代碼

  說明:在這個方法中,我們看到第一個事件(新的整數(100))是收到兩個聽眾,但第二個(新長(200 l))只能到達NumberListener作為整數一不是創建這種類型的事件。可以使用此功能來創建更通用的監聽器監聽一個廣泛的事件和更詳細的具體的特殊的事件。

   一個綜合實例:

復制代碼
public class UserThread extends Thread { private Socket connection; private EventBus channel; private BufferedReader in; private PrintWriter out; public UserThread(Socket connection, EventBus channel) { this.connection = connection; this.channel = channel; try { in = new BufferedReader(new InputStreamReader(connection.getInputStream())); out = new PrintWriter(connection.getOutputStream(), true); } catch (IOException e) { e.printStackTrace(); System.exit(1); } } @Subscribe public void recieveMessage(String message) { if (out != null) { out.println(message); System.out.println("recieveMessage:"+message); } } @Override public void run() { try { String input; while ((input = in.readLine()) != null) { channel.post(input); } } catch (IOException e) { e.printStackTrace(); } //reached eof channel.unregister(this); try { connection.close(); } catch (IOException e) { e.printStackTrace(); } in = null; out = null; } }
復制代碼
復制代碼
mport java.io.IOException;
import java.net.ServerSocket; import java.net.Socket; import com.google.common.eventbus.EventBus; public class EventBusChat { public static void main(String[] args) { EventBus channel = new EventBus(); ServerSocket socket; try { socket = new ServerSocket(4444); while (true) { Socket connection = socket.accept(); UserThread newUser = new UserThread(connection, channel); channel.register(newUser); newUser.start(); } } catch (IOException e) { e.printStackTrace(); } } }
復制代碼


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM