说下你可能没用过的EventBus(二)

发布于 2022-6-10 16:01
浏览
0收藏

 

除此之外,其实我们可以定义一个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就是提供了我们一个更优雅的代码解耦的方式,实际工作中的业务你肯定能用上它!

 

文章转自公众号:艾小仙

分类
标签
已于2022-6-10 16:01:19修改
收藏
回复
举报
回复
添加资源
添加资源将有机会获得更多曝光,你也可以直接关联已上传资源 去关联
    相关推荐