Guava-EventBus 详解

   EventBus是一个事件(消息)发布订阅框架,使用了观察者模式,可以同步也可以异步。选择同步还是异步就根据个人场景来进行选择。

AsyncEventBus就是异步的,是在EventBus的基础上,加入了Executor来异步执行订阅者处理事件的方法,这样就不会因为订阅事件执行过慢而阻塞主线程,源码如下:

@Beta
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);
    }
}

先通过代码看一下它简单的用法:

事件处理器1:

public class EventApple {

    @Subscribe
    public void eat(String apple){
        System.out.println("吃"+apple);
    }


}

事件处理器2:

public class EventRun {

    @Subscribe
    public void run(Integer run){
        System.out.println("跑步第"+run+"名");
    }
}

    注册事件处理器,发布事件。

public class TestEventBus {

    public static void main (String[] args){
        EventBus eventBus=new EventBus();

        eventBus.register(new EventApple());
        eventBus.register(new EventRun());
        eventBus.post(5);
        eventBus.post("苹果");

    }
}

输出:

跑步第5名
吃苹果

EventBus的基本用法就是:

1、创建EventBus对象,EventBus的构造函数,源码如下:

    public EventBus() {
        this("default");
    }

    public EventBus(String identifier) {
        this(identifier, MoreExecutors.directExecutor(), Dispatcher.perThreadDispatchQueue(), EventBus.LoggingHandler.INSTANCE);
    }

    public EventBus(SubscriberExceptionHandler exceptionHandler) {
        this("default", MoreExecutors.directExecutor(), Dispatcher.perThreadDispatchQueue(), exceptionHandler);
    }

    EventBus(String identifier, Executor executor, Dispatcher dispatcher, SubscriberExceptionHandler exceptionHandler) {
        this.subscribers = new SubscriberRegistry(this);
        this.identifier = (String)Preconditions.checkNotNull(identifier);
        this.executor = (Executor)Preconditions.checkNotNull(executor);
        this.dispatcher = (Dispatcher)Preconditions.checkNotNull(dispatcher);
        this.exceptionHandler = (SubscriberExceptionHandler)Preconditions.checkNotNull(exceptionHandler);
    }

构造函数有三个:

第一个是:创建一个新的EventBus对象,默认名称为default

第二个是:使用指定的标识符创建一个新的EventBus

第三个shi :使用SubscriberExceptionHandler ,处理subscribers处理事件时抛出异常。

2、注册事件处理器,源码:

void register(Object listener) {
        Multimap<Class<?>, Subscriber> listenerMethods = this.findAllSubscribers(listener);

        Collection eventMethodsInListener;
        CopyOnWriteArraySet eventSubscribers;
        for(Iterator var3 = listenerMethods.asMap().entrySet().iterator(); var3.hasNext(); eventSubscribers.addAll(eventMethodsInListener)) {
            Entry<Class<?>, Collection<Subscriber>> entry = (Entry)var3.next();
            Class<?> eventType = (Class)entry.getKey();
            eventMethodsInListener = (Collection)entry.getValue();
            eventSubscribers = (CopyOnWriteArraySet)this.subscribers.get(eventType);
            if (eventSubscribers == null) {
                CopyOnWriteArraySet<Subscriber> newSet = new CopyOnWriteArraySet();
                eventSubscribers = (CopyOnWriteArraySet)MoreObjects.firstNonNull(this.subscribers.putIfAbsent(eventType, newSet), newSet);
            }
        }

    }
事件处理器中要被执行的事件,都需要使用 @Subscribe注解,表示是注册的事件。

3、发布事件

 public void post(Object event) {
        Iterator<Subscriber> eventSubscribers = this.subscribers.getSubscribers(event);
        if (eventSubscribers.hasNext()) {
            this.dispatcher.dispatch(event, eventSubscribers);
        } else if (!(event instanceof DeadEvent)) {
            this.post(new DeadEvent(this, event));
        }

    }

发布事件之后,就去注册的事件处理器中查找有@Subscribe的注解的方法,找到对应参数类型的事件就执行。

如果在注册的处理器中没有找到发布的事件,那么EventBus就会把该事件包装成个DeadEvent事件来重新发布,我们可以提供下面的事件处理来处理DeadEvent:

 @Subscribe
    public void onEvent(DeadEvent de) {
        System.out.println("发布了错误的事件:" + de.getEvent());
    }

AsyncEventBus是异步的,只需要在AsyncEventBus的构造函数中添加Executor即可:

AsyncEventBus asyncEventBus=new AsyncEventBus(Executors.newFixedThreadPool(10));

其他操作和原始的EventBus是一样的。


EventBus中默认的订阅方式是线程不安全的,但是在异步调度的时候会自动将其包装成线程安全的。对于一般的线程安全的实现上可以通过@AllowConcurrentEvents注解来标示。

猜你喜欢

转载自blog.csdn.net/qiuhao9527/article/details/80986887
今日推荐