`

Google Guava EventBus简化生产/消费者模式使用

阅读更多


在Google Guava 10版本引入了EventBus, 它主要用来简化我们处理生产/消费者编程模型.

基本用法
使用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);
}


上面的测试是不是很简单?

MultiListener的使用

只需要在要订阅消息的方法上加上@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);
}


高级用法

1.Dead Event

如果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的方式来记录这种状态.

2.Event的继承

如果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);
}



参考原文:http://tomaszdziurko.pl/2012/01/google-guava-eventbus-easy-elegant-publisher-subscriber-cases/
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics