Google Guava EventBus簡化生產/消費者模式使用

在Google Guava 10版本引入了EventBus, 它主要用來簡化我們處理生產/消費者編程模型.

[b]基本用法[/b]
使用Guava之後, 如果要訂閱消息, 就不用再繼承指定的接口, 只需要在指定的方法上加上@Subscribe註解即可:

public class EventListener {

public int lastMessage = 0;

@Subscribe
public void listen(OurTestEvent event) {
lastMessage = event.getMessage();
}

public int getLastMessage() {
return lastMessage;
}
}


上面的lastMessage用來接收消息.

下面定義的類用來對消息進行封裝:

public class OurTestEvent {

private final int message;

public OurTestEvent(int message) {
this.message = message;
}

public int getMessage() {
return message;
}
}


通過寫一個測試來了解EventBus如何工作:

@Test
public void shouldReceiveEvent() throws Exception {

// given
EventBus eventBus = new EventBus("test");
EventListener listener = new EventListener();

eventBus.register(listener);

// when
eventBus.post(new OurTestEvent(200));

// then
assertThat(listener.getLastMessage()).isEqualTo(200);
}


上面的測試是不是很簡單?

[b]MultiListener的使用[/b]

只需要在要訂閱消息的方法上加上@Subscribe註解即可實現對多個消息的訂閱:
public class MultipleListener {

public Integer lastInteger;
public Long lastLong;

@Subscribe
public void listenInteger(Integer event) {
lastInteger = event;
}

@Subscribe
public void listenLong(Long event) {
lastLong = event;
}

public Integer getLastInteger() {
return lastInteger;
}

public Long getLastLong() {
return lastLong;
}
}


下面是對應的測試:

@Test
public void shouldReceiveMultipleEvents() throws Exception {

// given
EventBus eventBus = new EventBus("test");
MultipleListener multiListener = new MultipleListener();

eventBus.register(multiListener);

// when
eventBus.post(new Integer(100));
eventBus.post(new Long(800));

// then
assertThat(multiListener.getLastInteger()).isEqualTo(100);
assertThat(multiListener.getLastLong()).isEqualTo(800L);
}


[b]高級用法[/b]

[b]1.Dead Event[/b]

如果EventBus發送的消息都不是訂閱者關心的稱之爲Dead Event. 看下面的例子:
/**
* Listener waiting for the event that any message was posted but not delivered to anyone
*/
public class DeadEventListener {

boolean notDelivered = false;

@Subscribe
public void listen(DeadEvent event) {
notDelivered = true;
}

public boolean isNotDelivered() {
return notDelivered;
}
}


下面是測試類:

@Test
public void shouldDetectEventWithoutListeners() throws Exception {

// given
EventBus eventBus = new EventBus("test");

DeadEventListener deadEventListener = new DeadEventListener();
eventBus.register(deadEventListener);

// when
eventBus.post(new OurTestEvent(200));

assertThat(deadEventListener.isNotDelivered()).isTrue();
}


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

[b]2.Event的繼承[/b]

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

看下面的例子:

public class NumberListener {

private Number lastMessage;

@Subscribe
public void listen(Number integer) {
lastMessage = integer;
}

public Number getLastMessage() {
return lastMessage;
}
}


public class IntegerListener {

private Integer lastMessage;

@Subscribe
public void listen(Integer integer) {
lastMessage = integer;
}

public Integer getLastMessage() {
return lastMessage;
}
}


對應的測試類:


@Test
public void shouldGetEventsFromSubclass() throws Exception {

// given
EventBus eventBus = new EventBus("test");
IntegerListener integerListener = new IntegerListener();
NumberListener numberListener = new NumberListener();
eventBus.register(integerListener);
eventBus.register(numberListener);

// when
eventBus.post(new Integer(100));

// then
assertThat(integerListener.getLastMessage()).isEqualTo(100);
assertThat(numberListener.getLastMessage()).isEqualTo(100);

//when
eventBus.post(new Long(200L));

// then
// this one should has the old value as it listens only for Integers
assertThat(integerListener.getLastMessage()).isEqualTo(100);
assertThat(numberListener.getLastMessage()).isEqualTo(200L);
}



參考原文:[url]http://tomaszdziurko.pl/2012/01/google-guava-eventbus-easy-elegant-publisher-subscriber-cases/[/url]
發佈了264 篇原創文章 · 獲贊 4 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章