其实代码中经常会遇到跟主流程分支出去的异步逻辑,比如说:
爬虫处理逻辑中,进行心跳打点,订单处理中,需要触发用户的个人信息变更等。
这个时候就应该使用观察者模式。
EventBus是Guava的事件处理机制,是设计模式中的观察者模式(生产/消费者编程模型)的优雅实现。对于事件监听和发布订阅模式,EventBus是一个非常优雅和简单解决方案,我们不用创建复杂的类和接口层次结构。
import com.google.common.eventbus.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;
}
}
import com.google.common.eventbus.Subscribe;
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;
}
}
import com.google.common.eventbus.EventBus;
public class TestEventBusMain {
public static 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());
}
public static void testReceiveEvent() {
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());
}
public static void main(String[] args) throws Exception {
testMultipleEvents() ;
}
}
实际上EventBus要表达的意图很简单,就是将post(Object arg)这里的arg当做参数传入到已注册的方法(被@Subscribe)的方法里,并调用该方法,所以当post(String)的时候,调用的参数类型为String的注册方法,当post(int)的时候,调用则是参数类型为Integer的注册方法。
在多线程的结构下,可以使用AsyncEventBus
public void testAysncEventBus() {
AsyncEventBus eventBus = new AsyncEventBus(Executors.newFixedThreadPool(3));
eventBus.register(new EventListener());
eventBus.post("ssdf");
System.out.println("==");
}
但是作为异步调用,EventBus的封装显得比较单薄。
parseq对于异步的包装则非常令人称赞。