首页 > 代码库 > Guava源码学习(五)EventBus

Guava源码学习(五)EventBus

基于版本:Guava 22.0

Wiki:EventBus

 

0. EventBus简介

提供了发布-订阅模型,可以方便的在EventBus上注册订阅者,发布者可以简单的将事件传递给EventBus,EventBus会自动将事件传递给相关联的订阅者。

支持同步/异步模式。

只能用于线程间通信。

 

1. EventBus类图

技术分享

EventBus是同步实现

AsyncEventBus是异步实现

 

2. 代码实例

        EventBus eventBus = new EventBus();
        
        eventBus.register(new Object() {
            @Subscribe
            public void listen(Object subReport) throws Exception {
                System.out.println("receive object event!");
            }

            @Subscribe
            public void listen(Integer subReport) throws Exception {
                System.out.println("receive integer event!");
            }
        });

        eventBus.post(Integer.valueOf(1));

这段代码的输出如下:

receive integer event!
receive object event!

 

3. EventBus.register()

EventBus.register
  /**
   * Registers all subscriber methods on {@code object} to receive events.
   *
   * @param object object whose subscriber methods should be registered.
   */
  public void register(Object object) {
    subscribers.register(object);
  }


SubscriberRegistry.register
  /**
   * Registers all subscriber methods on the given listener object.
   */
  void register(Object listener) {
    Multimap<Class<?>, Subscriber> listenerMethods = findAllSubscribers(listener);//获取传入的listener中含有的所有的监听者

    for (Map.Entry<Class<?>, Collection<Subscriber>> entry : listenerMethods.asMap().entrySet()) {
      Class<?> eventType = entry.getKey();//监听的事件类型
      Collection<Subscriber> eventMethodsInListener = entry.getValue();//对应的监听器本身

      CopyOnWriteArraySet<Subscriber> eventSubscribers = subscribers.get(eventType);

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

      eventSubscribers.addAll(eventMethodsInListener);
    }
  }


  /**
   * Returns all subscribers for the given listener grouped by the type of event they subscribe to.
    分析传入的对象,遍历其中所有含有Subscribe注解而且只含有一个参数的方法,然后将其包装成监听者并返回。
   */
  private Multimap<Class<?>, Subscriber> findAllSubscribers(Object listener) {
    Multimap<Class<?>, Subscriber> methodsInListener = HashMultimap.create();
    Class<?> clazz = listener.getClass();
    for (Method method : getAnnotatedMethods(clazz)) {//getAnnotatedMethods方法最终会调用到下面的SubscriberRegistry.getAnnotatedMethodsNotCached方法,这个方法会用反射处理传入的clazz及其所有的父类,提取出含有Subscribe注解并且有且只有一个参数的方法
      Class<?>[] parameterTypes = method.getParameterTypes();
      Class<?> eventType = parameterTypes[0];//获取这个方法的唯一参数的Class
      methodsInListener.put(eventType, Subscriber.create(bus, listener, method));//将EventBus,监听者对象,监听者方法包装一下并放入map,后续触发事件的时候会用到
    }
    return methodsInListener;
  }

SubscriberRegistry.getAnnotatedMethodsNotCached
  private static ImmutableList<Method> getAnnotatedMethodsNotCached(Class<?> clazz) {
    Set<? extends Class<?>> supertypes = TypeToken.of(clazz).getTypes().rawTypes();//连clazz的父类也会处理
    Map<MethodIdentifier, Method> identifiers = Maps.newHashMap();
    for (Class<?> supertype : supertypes) {
      for (Method method : supertype.getDeclaredMethods()) {
        if (method.isAnnotationPresent(Subscribe.class) && !method.isSynthetic()) {//含有Subscribe注解,而且不是合成的方法
          // TODO(cgdecker): Should check for a generic parameter type and error out
          Class<?>[] parameterTypes = method.getParameterTypes();
          checkArgument(
              parameterTypes.length == 1,
              "Method %s has @Subscribe annotation but has %s parameters."
                  + "Subscriber methods must have exactly 1 parameter.",
              method,
              parameterTypes.length);//方法必须有且只有一个参数

          MethodIdentifier ident = new MethodIdentifier(method);
          if (!identifiers.containsKey(ident)) {
            identifiers.put(ident, method);
          }
        }
      }
    }
    return ImmutableList.copyOf(identifiers.values());
  }

 

Guava源码学习(五)EventBus