说下你可能没用过的EventBus(二)
除此之外,其实我们可以定义一个DeadEvent来处理这种情况,它相当于是一个默认的处理方式,当没有匹配的事件类型参数的话就会默认发送一个DeadEvent事件。
定义一个默认处理器。
public class DefaultEventHandler {
@Subscribe
public void handle(DeadEvent event) {
System.out.println("no subscriber," + event);
}
}
给BookingService新增一个pay()支付方法,下单完了去支付,注册我们的默认事件。
public void pay(){
//业务逻辑
eventBus.register(new DefaultEventHandler());
eventBus.post(new Payment(UUID.randomUUID().toString()));
}
@ToString
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Payment {
private String paymentId;
}
执行测试bookingService.pay()看到输出结果:
no subscriber,DeadEvent{source=AsyncEventBus{default}, event=Payment(paymentId=255da942-7128-4bd1-baca-f0a8e569ed88)}
源码分析
OK,简单的介绍就到这里,那其实到目前为止我们说的这个都是同步调用的,这不太符合我们的要求,我们当然使用异步处理更好。
那就看看源码它是怎么实现的。
@Beta
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 = new SubscriberRegistry(this);
private final Dispatcher dispatcher;
public EventBus() {
this("default");
}
public EventBus(String identifier) {
this(
identifier,
MoreExecutors.directExecutor(),
Dispatcher.perThreadDispatchQueue(),
LoggingHandler.INSTANCE);
}
}
identifier就是个名字,标记,默认就是default。
executor执行器,默认创建一个MoreExecutors.directExecutor(),事件订阅者根据你自己提供的executor来决定如何执行事件订阅的处理方式。
exceptionHandler是异常处理器,默认创建的就是打点日志。
subscribers就是我们的消费者,订阅者。
dispatcher用来做事件分发。
默认创建的executor是一个MoreExecutors.directExecutor(),看到command.run()你就会发现他这不就是同步执行嘛。
public static Executor directExecutor() {
return DirectExecutor.INSTANCE;
}
private enum DirectExecutor implements Executor {
INSTANCE;
@Override
public void execute(Runnable command) {
command.run();
}
@Override
public String toString() {
return "MoreExecutors.directExecutor()";
}
同步执行还是不太好,我们希望不光给我们解耦,还要异步执行,EventBus给我们提供了AsyncEventBus,Executor我们自己传入就好了。
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);
}
上面的代码我们改成异步的,这样不就好起来了嘛,这样的话,实际上可以结合我们自己的线程池来处理了。
private static AsyncEventBus eventBus = new AsyncEventBus(Executors.newFixedThreadPool(3));
OK,这个说清楚了,我们可以顺便再看看事件分发的处理,看到DeadEvent了吧,没有当前事件的订阅者,就会发送一个DeadEvent事件,bingo!
public void post(Object event) {
Iterator<Subscriber> eventSubscribers = subscribers.getSubscribers(event);
if (eventSubscribers.hasNext()) {
dispatcher.dispatch(event, eventSubscribers);
} else if (!(event instanceof DeadEvent)) {
// the event had no subscribers and was not itself a DeadEvent
post(new DeadEvent(this, event));
}
}
总结
OK,这个使用和源码还是比较简单的哈,有兴趣的同学可以自己去瞅瞅,花不了多少工夫。
总的来说,EventBus就是提供了我们一个更优雅的代码解耦的方式,实际工作中的业务你肯定能用上它!
文章转自公众号:艾小仙