Google EventBus源码分析

1.订阅者注册中心


1.1 订阅者存放结构

线程安全的Map,key订阅者订阅的事件class,value为接收此事件对应的方法

 private final ConcurrentMap, CopyOnWriteArraySet> subscribers =
      Maps.newConcurrentMap();

1.2 订阅者注册

 /**注册订阅者 所有的订阅方法*/
  void register(Object listener) {
    Multimap, Subscriber> listenerMethods = findAllSubscribers(listener);

    for (Entry, Collection> entry : listenerMethods.asMap().entrySet()) {
      /**事件的数据类型*/
      Class eventType = entry.getKey();

      /**接收此事件的订阅者*/
      Collection eventMethodsInListener = entry.getValue();

      CopyOnWriteArraySet eventSubscribers = subscribers.get(eventType);

      if (eventSubscribers == null) {
        CopyOnWriteArraySet newSet = new CopyOnWriteArraySet<>();
        eventSubscribers =
            MoreObjects.firstNonNull(subscribers.putIfAbsent(eventType, newSet), newSet);
      }

      eventSubscribers.addAll(eventMethodsInListener);
    }
  }

1.3订阅者抽象类

class Subscriber {

  /**支持创建线程安全的方法*/
  static Subscriber create(EventBus bus, Object listener, Method method) {
    return isDeclaredThreadSafe(method)
        ? new Subscriber(bus, listener, method)
        : new SynchronizedSubscriber(bus, listener, method);
  }

  /** The event bus this subscriber belongs to. */
  /**订阅者所属的 事件总线*/
  @Weak private EventBus bus;

  /** The object with the subscriber method. */
  @VisibleForTesting final Object target;

  /** Subscriber method. */
  /**订阅者的方法*/
  private final Method method;

  ...

  /**分发事件给自己进行执行相关方法*/
  //event为订阅者订阅方法参数
  final void dispatchEvent(final Object event) {
    executor.execute(
        new Runnable() {
          @Override
          public void run() {
            try {
               //调用订阅者的方法
              invokeSubscriberMethod(event);
            } catch (InvocationTargetException e) {
              bus.handleSubscriberException(e.getCause(), context(event));
            }
          }
        });
  }
1.4 调用订阅者的方法
 /**
   * Invokes the subscriber method. This method can be overridden to make the invocation
   * synchronized.
   *
   * 调用调用者的方法
   */
  @VisibleForTesting
  void invokeSubscriberMethod(Object event) throws InvocationTargetException {
    try {
      /**java方法调用*/
      method.invoke(target, checkNotNull(event));
    } catch (IllegalArgumentException e) {
      throw new Error("Method rejected target/argument: " + event, e);
    } catch (IllegalAccessException e) {
      throw new Error("Method became inaccessible: " + event, e);
    } catch (InvocationTargetException e) {
      if (e.getCause() instanceof Error) {
        throw (Error) e.getCause();
      }
      throw e;
    }
  }

2.分发器(Dispather)


分发器的主要作用是把产生的事件分发给订阅者;

2.1 没有中间队列的分发器

把事件直接交给分发器,不适用队列

private static final class ImmediateDispatcher extends Dispatcher {
    private static final ImmediateDispatcher INSTANCE = new ImmediateDispatcher();

    @Override
    void dispatch(Object event, Iterator subscribers) {
      checkNotNull(event);
      while (subscribers.hasNext()) {
        subscribers.next().dispatchEvent(event);
      }
    }
  }
}

2.2 使用全局队列的分发器

不能保证事件的有序性

 /** Implementation of a {@link #legacyAsync()} dispatcher. */
  /**
   * 传统的异步分发实现
   * 所有的事件都放到一个全局的队列里
   */
  private static final class LegacyAsyncDispatcher extends Dispatcher {

    /** Global event queue. */
    /**全局的事件队列*/
    private final ConcurrentLinkedQueue queue =
        Queues.newConcurrentLinkedQueue();

    @Override
    void dispatch(Object event, Iterator subscribers) {
      checkNotNull(event);
      while (subscribers.hasNext()) {
        queue.add(new EventWithSubscriber(event, subscribers.next()));
      }

      EventWithSubscriber e;
      while ((e = queue.poll()) != null) {
        e.subscriber.dispatchEvent(e.event);
      }
    }

    private static final class EventWithSubscriber {
      private final Object event;
      private final Subscriber subscriber;

      private EventWithSubscriber(Object event, Subscriber subscriber) {
        this.event = event;
        this.subscriber = subscriber;
      }
    }
  }

2.3 每个线程队列分发器实现

每个线程有一个自己的队列,线程把自己的产生的事件存放到跟自己相关的队列中。
同一个线程只能进入dipatcher方法一次,保证消息的顺序性。

 /**
   * 每个线程有个对应的队列的分发器
   * 同一个线程时互斥的,只能同一个线程进入dispatcher进入。
   */
  private static final class PerThreadQueuedDispatcher extends Dispatcher {

    // This dispatcher matches the original dispatch behavior of EventBus.

    /** Per-thread queue of events to dispatch. */
    /**
     * 每个线程对应的事件队列
     */
    private final ThreadLocal> queue =
        new ThreadLocal>() {
          @Override
          protected Queue initialValue() {
            return Queues.newArrayDeque();
          }
        };

    /** Per-thread dispatch state, used to avoid reentrant event dispatching. */
    /**
     * 每个线程分发状态,使用它为了避免重新进入分发事件
     */
    private final ThreadLocal dispatching =
        new ThreadLocal() {
          @Override
          protected Boolean initialValue() {
            return false;
          }
        };

    @Override
    void dispatch(Object event, Iterator subscribers) {
      checkNotNull(event);
      checkNotNull(subscribers);
      Queue queueForThread = queue.get();
      queueForThread.offer(new Event(event, subscribers));
      /**标记线程重复进入*/
      if (!dispatching.get()) {
        dispatching.set(true);
        try {
          Event nextEvent;
          while ((nextEvent = queueForThread.poll()) != null) {
            while (nextEvent.subscribers.hasNext()) {
              nextEvent.subscribers.next().dispatchEvent(nextEvent.event);
            }
          }
        } finally {
          dispatching.remove();
          queue.remove();
        }
      }
    }

    private static final class Event {
      private final Object event;
      private final Iterator subscribers;

      private Event(Object event, Iterator subscribers) {
        this.event = event;
        this.subscribers = subscribers;
      }
    }
  }

3.事件线实现 EventBus


EventBus 用来注册订阅者、卸载订阅者、提交订阅事件等。

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;

  ....

}

4. 总结


  1. 事件灵活,可以是任何java类
  2. 使用注解的方式订阅事件
  3. 父类也可以订阅事件

你可能感兴趣的:(EventBus)