otto源代码分析

0 使用手册http://square.github.io/otto/

基本原理

使用@Subscribe注解一个Event事件处理方法和@Produce注解一个Event事件生成方法,在register的时候利用反射将这些方法按照Event类型保存在Map中,当使用Bus.post(Object event)时,在Map中找到event对应的事件处理方法,然后分别调用一遍,来实现事件总线的功能。

数据结构分析

0.1  ThreadEnforcer:该类用于对调用线程进行检查,若不满足条件则跑出异常。例如:

ThreadEnforcer MAIN = new ThreadEnforcer() {
    @Override public void enforce(Bus bus) {
      if (Looper.myLooper() != Looper.getMainLooper()) {
        throw new IllegalStateException("Event bus " + bus + " accessed from non-main thread " + Looper.myLooper());
      }
    }
  };


0.2 EventProducer:该类表示一个注解了Produce的方法。target字段表示register时的对象,method字段是该方法的反射。需要产生event对象时,直接调用method.invoke(target)即可。

0.3 EventHandler:该类表示一个注解了Subscribe的方法。同样target字段表示register时的对象,method字段是该方法的反射。有post event对象时,直接调用method.invoke(target, event)即可。

0.4 DeadEvent: 如果post一个event事件时,没有对应的subscribe的方法,则post该DeadEvent对象。source字段表示是由哪个对象post出来的,event表示没有subscribe的那个事件。

0.5 AnnotatedHandlerFinder:该类用于在register和unregister时,查找这个对象的所有Subscribe和Produce方法。

0.6 Bus:事件总线类,该类用来注解了Produce和Subscribe的对象注册到总线上,需要时使用该总线post一个event事件,即可调用注解了Subscribe的方法。

1 初始化

手册建议(不强制)单例模式使用Bus。代码如下:

public final class BusProvider {
  private static final Bus BUS = new Bus();

  public static Bus getInstance() {
    return BUS;
  }

  private BusProvider() {
    // No instances.
  }
}
初始化过程中,初始化ThreadEnforcer,HandlerFinder,前者用于设置调用post,register,unregister是否检查调用线程,确保是主线程;后者用于register时在找出所有注解有Subsribe和Produce的方法。

Bus(ThreadEnforcer enforcer, String identifier, HandlerFinder handlerFinder) {
    this.enforcer =  enforcer;
    this.identifier = identifier;
    this.handlerFinder = handlerFinder;
}  

 

2 register

  public void register(Object object) {
    if (object == null) {
      throw new NullPointerException("Object to register must not be null.");
    }

    //检查调用线程
    enforcer.enforce(this);

    //找出object对象的所有标记有Produce的方法,为每一个方法生成一个<Class<?>,EventProducer>,其中Class<?>为方法返回值,EventProducer表示注解的方法。然后检查Class<?>的Produce方法是否唯一,然后为每一个Class<?>调用对应Subscribe方法

    Map<Class<?>, EventProducer> foundProducers = handlerFinder.findAllProducers(object);
    for (Class<?> type : foundProducers.keySet()) {


      final EventProducer producer = foundProducers.get(type);
      EventProducer previousProducer = producersByType.putIfAbsent(type, producer);
      //checking if the previous producer existed
      if (previousProducer != null) {
        throw new IllegalArgumentException("Producer method for type " + type
          + " found on type " + producer.target.getClass()
          + ", but already registered by type " + previousProducer.target.getClass() + ".");
      }
      Set<EventHandler> handlers = handlersByType.get(type);
      if (handlers != null && !handlers.isEmpty()) {
        for (EventHandler handler : handlers) {
          dispatchProducerResultToHandler(handler, producer);
        }
      }
    }

    //找出object对象的所有标记有Subscribe的方法,为每一个方法生成一个<Class<?>,Set<EventHandler>>,其中Class<?>为方法参数,有且仅有一个,EventHandler表示注解Subscribe的方法。然后检查Class<?>是否已经注册过,然后为每一个Class<?>调用对应已经注册Produce方法生成一个event,使用该event调用对应的所有EventHandler
    Map<Class<?>, Set<EventHandler>> foundHandlersMap = handlerFinder.findAllSubscribers(object);
    for (Class<?> type : foundHandlersMap.keySet()) {
      Set<EventHandler> handlers = handlersByType.get(type);
      if (handlers == null) {
        //concurrent put if absent
        Set<EventHandler> handlersCreation = new CopyOnWriteArraySet<EventHandler>();
        handlers = handlersByType.putIfAbsent(type, handlersCreation);
        if (handlers == null) {
            handlers = handlersCreation;
        }
      }
      final Set<EventHandler> foundHandlers = foundHandlersMap.get(type);
      if (!handlers.addAll(foundHandlers)) {
        throw new IllegalArgumentException("Object already registered.");
      }
    }


    for (Map.Entry<Class<?>, Set<EventHandler>> entry : foundHandlersMap.entrySet()) {
      Class<?> type = entry.getKey();
      EventProducer producer = producersByType.get(type);
      if (producer != null && producer.isValid()) {
        Set<EventHandler> foundHandlers = entry.getValue();
        for (EventHandler foundHandler : foundHandlers) {
          if (!producer.isValid()) {
            break;
          }
          if (foundHandler.isValid()) {
            dispatchProducerResultToHandler(foundHandler, producer);
          }
        }
      }
    }
  }

3 unregister

  public void unregister(Object object) {
    if (object == null) {
      throw new NullPointerException("Object to unregister must not be null.");
    }
    enforcer.enforce(this);

      //找出所有注解有Produce的方法,将每一个方法从Map中移除
    Map<Class<?>, EventProducer> producersInListener = handlerFinder.findAllProducers(object);
    for (Map.Entry<Class<?>, EventProducer> entry : producersInListener.entrySet()) {
      final Class<?> key = entry.getKey();
      EventProducer producer = getProducerForEventType(key);
      EventProducer value = entry.getValue();

      if (value == null || !value.equals(producer)) {
        throw new IllegalArgumentException(
            "Missing event producer for an annotated method. Is " + object.getClass()
                + " registered?");
      }
      producersByType.remove(key).invalidate();
    }

    //找出所有注解有Subscribe的方法,将每一个方法从Map中移除
    Map<Class<?>, Set<EventHandler>> handlersInListener = handlerFinder.findAllSubscribers(object);
    for (Map.Entry<Class<?>, Set<EventHandler>> entry : handlersInListener.entrySet()) {
      Set<EventHandler> currentHandlers = getHandlersForEventType(entry.getKey());
      Collection<EventHandler> eventMethodsInListener = entry.getValue();

      if (currentHandlers == null || !currentHandlers.containsAll(eventMethodsInListener)) {
        throw new IllegalArgumentException(
            "Missing event handler for an annotated method. Is " + object.getClass()
                + " registered?");
      }

      for (EventHandler handler : currentHandlers) {
        if (eventMethodsInListener.contains(handler)) {
          handler.invalidate();
        }
      }
      currentHandlers.removeAll(eventMethodsInListener);
    }
  }


4 post

public void post(Object event) {
    if (event == null) {
      throw new NullPointerException("Event to post must not be null.");
    }
    enforcer.enforce(this);

    Set<Class<?>> dispatchTypes = flattenHierarchy(event.getClass());

    boolean dispatched = false;
    //根据event的类型将event分成event类型,event类型的父类型....并找出所有Subscribe的方法,即EventHandler    //,为每一个EventHandler生成一个
    //EventWithHandler对象,放入处理队列eventsToDispatch中,分别调用一遍,如果没有Subscribe该Event的方法     //则post一个DeadEvent。    //    for (Class<?> eventType : dispatchTypes) {
      Set<EventHandler> wrappers = getHandlersForEventType(eventType);

      if (wrappers != null && !wrappers.isEmpty()) {
        dispatched = true;
        for (EventHandler wrapper : wrappers) {
          //放入处理队列eventsToDispatch中
          enqueueEvent(event, wrapper);
        }
      }
    }

    if (!dispatched && !(event instanceof DeadEvent)) {
      post(new DeadEvent(this, event));
    }
    dispatchQueuedEvents();
  }

4.1 dispatchQueuedEvents

该函数重点分析的原因是该函数的实现方式,避免了函数重入和处理乱序的问题,值得借鉴。

  protected void dispatchQueuedEvents() {
    // don't dispatch if we're already dispatching, that would allow reentrancy and out-of-order events. Instead, leave
    // the events to be dispatched after the in-progress dispatch is complete.

    //当前线程如果在处理过程中又post一个event,则会重入该函数,并且后post的事件会先处理。这里为了避免这个情况,利用一个队列,将post的事件放入队列中,    //然后按入队的顺序处理这些事件。                                                                                                     if (isDispatching.get()) {
      return;
    }

    isDispatching.set(true);
    try {
      while (true) {
        EventWithHandler eventWithHandler = eventsToDispatch.get().poll();
        if (eventWithHandler == null) {
          break;
        }

        if (eventWithHandler.handler.isValid()) {
          dispatch(eventWithHandler.event, eventWithHandler.handler);
        }
      }
    } finally {
      isDispatching.set(false);
    }
  }


 

 

5 AnnotatedHandlerFinder类分析

该类有两个静态域:PRODUCERS_CACHE和SUBSCRIBERS_CACHE,都是Map类型,这两个域用于缓存一个对象上所有注解了@Subscribe和@Produce的方法,其中Key为调用Bus.register(Object object)方法和Bus.unregister(Object object)方法时object对象的类型;Value也是一个Map,Value Map的Key为注解方法的事件类型,对应注解@Subscribe的方法是方法参数,注解@Produce的方法是方法返回值,Value Map的Value是方法的反射类型Method。其中对于一个Event事件@Subscribe方法可能会有多个,但是@Produce方法只会有一个,所有前者用Set<Method>保存,后者用Method保存。

 private static void loadAnnotatedMethods(Class<?> listenerClass) {
    Map<Class<?>, Set<Method>> subscriberMethods = new HashMap<Class<?>, Set<Method>>();
    Map<Class<?>, Method> producerMethods = new HashMap<Class<?>, Method>();

    //遍历每一个method,进行必要的判断,
    //如果注解了@Subscribe则保证只有一个参数,方法是Public的,
    //如果是注解了@Produce则保证一定是注解在类上,方法是Public的,返回值不是void类型.
    //然后按照event类型将所有@Subscribe方法保存在一个Map中,@Produce方法保存在另外一个Map中,
    //最后按照listenerClass,即register(Object object)时object的类型分别保存在PRODUCERS_CACHE
    //和SUBSCRIBERS_CACHE中。
    for (Method method : listenerClass.getDeclaredMethods()) {
      // The compiler sometimes creates synthetic bridge methods as part of the
      // type erasure process. As of JDK8 these methods now include the same
      // annotations as the original declarations. They should be ignored for
      // subscribe/produce.
      if (method.isBridge()) {
        continue;
      }
      if (method.isAnnotationPresent(Subscribe.class)) {
        Class<?>[] parameterTypes = method.getParameterTypes();
        if (parameterTypes.length != 1) {
          throw new IllegalArgumentException("Method " + method + " has @Subscribe annotation but requires "
              + parameterTypes.length + " arguments.  Methods must require a single argument.");
        }

        Class<?> eventType = parameterTypes[0];
        if (eventType.isInterface()) {
          throw new IllegalArgumentException("Method " + method + " has @Subscribe annotation on " + eventType
              + " which is an interface.  Subscription must be on a concrete class type.");
        }

        if ((method.getModifiers() & Modifier.PUBLIC) == 0) {
          throw new IllegalArgumentException("Method " + method + " has @Subscribe annotation on " + eventType
              + " but is not 'public'.");
        }

        Set<Method> methods = subscriberMethods.get(eventType);
        if (methods == null) {
          methods = new HashSet<Method>();
          subscriberMethods.put(eventType, methods);
        }
        methods.add(method);
      } else if (method.isAnnotationPresent(Produce.class)) {
        Class<?>[] parameterTypes = method.getParameterTypes();
        if (parameterTypes.length != 0) {
          throw new IllegalArgumentException("Method " + method + "has @Produce annotation but requires "
              + parameterTypes.length + " arguments.  Methods must require zero arguments.");
        }
        if (method.getReturnType() == Void.class) {
          throw new IllegalArgumentException("Method " + method
              + " has a return type of void.  Must declare a non-void type.");
        }

        Class<?> eventType = method.getReturnType();
        if (eventType.isInterface()) {
          throw new IllegalArgumentException("Method " + method + " has @Produce annotation on " + eventType
              + " which is an interface.  Producers must return a concrete class type.");
        }
        if (eventType.equals(Void.TYPE)) {
          throw new IllegalArgumentException("Method " + method + " has @Produce annotation but has no return type.");
        }

        if ((method.getModifiers() & Modifier.PUBLIC) == 0) {
          throw new IllegalArgumentException("Method " + method + " has @Produce annotation on " + eventType
              + " but is not 'public'.");
        }

        if (producerMethods.containsKey(eventType)) {
          throw new IllegalArgumentException("Producer for type " + eventType + " has already been registered.");
        }
        producerMethods.put(eventType, method);
      }
    }

    PRODUCERS_CACHE.put(listenerClass, producerMethods);
    SUBSCRIBERS_CACHE.put(listenerClass, subscriberMethods);
  }

  /** This implementation finds all methods marked with a {@link Produce} annotation. */
  static Map<Class<?>, EventProducer> findAllProducers(Object listener) {
    final Class<?> listenerClass = listener.getClass();
    Map<Class<?>, EventProducer> handlersInMethod = new HashMap<Class<?>, EventProducer>();

    if (!PRODUCERS_CACHE.containsKey(listenerClass)) {
      loadAnnotatedMethods(listenerClass);
    }
      //从PRODUCERS_CACHE中找出出listener类所有的@Produce方法,为每一个方法生成一个
      //EventProducer,放入handlersInMethod中,handlersInMethod中的Key为事件类型,
      //即@Produce方法的返回值类型
    Map<Class<?>, Method> methods = PRODUCERS_CACHE.get(listenerClass);
    if (!methods.isEmpty()) {
      for (Map.Entry<Class<?>, Method> e : methods.entrySet()) {
        EventProducer producer = new EventProducer(listener, e.getValue());
        handlersInMethod.put(e.getKey(), producer);
      }
    }

    return handlersInMethod;
  }

  /** This implementation finds all methods marked with a {@link Subscribe} annotation. */
  static Map<Class<?>, Set<EventHandler>> findAllSubscribers(Object listener) {
    Class<?> listenerClass = listener.getClass();
    Map<Class<?>, Set<EventHandler>> handlersInMethod = new HashMap<Class<?>, Set<EventHandler>>();

    if (!SUBSCRIBERS_CACHE.containsKey(listenerClass)) {
      loadAnnotatedMethods(listenerClass);
    }
      //SUBSCRIBERS_CACHE找出所有的@Subscribe方法,为每一个方法生成一个
      //EventHandler,放入handlersInMethod中,handlersInMethod中的Key为事件类型,
      //即@Subscribe方法的参数类型
    Map<Class<?>, Set<Method>> methods = SUBSCRIBERS_CACHE.get(listenerClass);
    if (!methods.isEmpty()) {
      for (Map.Entry<Class<?>, Set<Method>> e : methods.entrySet()) {
        Set<EventHandler> handlers = new HashSet<EventHandler>();
        for (Method m : e.getValue()) {
          handlers.add(new EventHandler(listener, m));
        }
        handlersInMethod.put(e.getKey(), handlers);
      }
    }

    return handlersInMethod;
  }


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值