otto 源码

otto 源码

05 February 2016

Otto 的源码非常简单,一共就九个类。




项目结构

  • AnnotatedHandlerFinder ( 查找并缓存所有注解方法 )
  • Bus ( otto 核心业务类,包括注册、反注册、发送事件等等 )
  • DeadEvent ( 内置事件,没有订阅者,不能被传递 )
  • EventHandler ( 封装 @Subscribe 方法及其所在类 )
  • EventProducer ( 封装 @Produce 方法及其所在类 )
  • HandlerFinder ( 调用 AnnotatedHandlerFinder 的方法拿到注解方法,封装成 EventHandler 和 EventProducer 的集合 )
  • Produce ( @Produce )
  • Subscribe ( @Subscribe )
  • ThreadEnforcer ( 用于切换线程 )




register 实现


处理 @Produce 逻辑

  • 1.通过 AnnotatedHandlerFinder 找到 @Produce 方法
  • 2.然后 HandlerFinder 经由找回来的封装成Map<Class<?>, EventProducer>集合
  • 3.遍历 Map<Class<?>, EventProducer> 集合,逐个拿到该类对应的全部缓存的 EventHandler
  • 4.这样就凑齐了 @Subscribe@Produce 方法
  • 5.调用 dispatchProducerResultToHandler 处理:所谓的 提供 @Produce 被自身 @Subscribe 消费的流程
/**
 * 通过 HandlerFinder 找到所有
 * object 里所有 @Produce 方法
 * 找回来的封装成 EventProducer
 * 并且最后返回 Map<Class<?>, EventProducer>
 */
Map<Class<?>, EventProducer> foundProducers = handlerFinder.findAllProducers(object);  
for (Class<?> type : foundProducers.keySet()) {

    /**
     * 逐个拿到EventProducer
     */
    final EventProducer producer = foundProducers.get(type);
    /**
     * ConcurrentMap putIfAbsent 安全的put
     * 防止并发
     * 查看缓存 ConcurrentMap<Class<?>, EventProducer> 有木有
     */
    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() + ".");
    }

    /**
     * 逐个拿到全部缓存EventHandler ( @Subscribe方法封装类 )
     */
    Set<EventHandler> handlers = handlersByType.get(type);
    if (handlers != null && !handlers.isEmpty()) {
        for (EventHandler handler : handlers) {
            /**
             * 逐个去调用@Subscribe 和 @Produce 方法
             */
            dispatchProducerResultToHandler(handler, producer);
        }
    }
}


处理 @SubScribe 逻辑

  • 1.通过 AnnotatedHandlerFinder 找到 @Subscribe 方法
  • 2.然后 HandlerFinder 经由找回来的封装成 Map<Class<?>, Set<EventHandler>> 集合
  • 3.先遍历Map<Class<?>, Set<EventHandler>>集合,拿到 Set<EventHandler>刷新缓存
  • 4.再次循环 Map<Class<?>, Set<EventHandler>> 集合,查找对应类的 Set<EventProducer> 缓存。
  • 6.调用 dispatchProducerResultToHandler 处理,再一次完成:所谓的 提供 @Produce 被自身 @Subscribe 消费的流程
/**
 * 通过 HandlerFinder 找到所有
 * object 里所有 @SubScribe 方法
 * 找回来的封装成 EventHandler
 * Map<Class<?>, Set<EventHandler>>
 */
Map<Class<?>, Set<EventHandler>> foundHandlersMap = handlerFinder.findAllSubscribers(object);

/**
 * 逐个拿到 EventHandler
 */
for (Class<?> type : foundHandlersMap.keySet()) {

    /**
     * 拿到缓存 EventHandler 集合
     */
    Set<EventHandler> handlers = handlersByType.get(type);
    if (handlers == null) {
        //concurrent put if absent
        Set<EventHandler> handlersCreation = new CopyOnWriteArraySet<EventHandler>();

        /**
         * 往缓存 EventHandler Map 里放入一份 type 对应的 EventHandle 集合
         */
        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.");
    }
}

/**
 * 遍历所有找到 EventHandler ( @Subscribe方法 )
 */
for (Map.Entry<Class<?>, Set<EventHandler>> entry : foundHandlersMap.entrySet()) {  
    Class<?> type = entry.getKey();
    /**
     * 再拿一次 EventProducer 缓存
     * 如果object 里 存在 @Producer 方法
     * 才循环 EventHandler 的逻辑里去 调用
     * dispatchProducerResultToHandler方法
     */
    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);
            }
        }
    }
}




unregister 实现

  • 1.通过 AnnotatedHandlerFinder 找到 @Produce 方法
  • 2.然后 HandlerFinder 经由找回来的封装成Map<Class<?>, EventProducer>集合
  • 3.遍历 Map<Class<?>, EventProducer> 集合,逐个拿到EventProducer,并去查找是否存在该 EventProducer 缓存。
  • 4.存在缓存 ,从 EventProducer 缓存 Map 里移除,调用 EventProducer.invalidate() 方法
/**
 * 通过  HandlerFinder找到所有
 * object 里所有 @Produce 方法
 * 找回来的封装成 EventProducer
 * 并且最后返回 Map<Class<?>, EventProducer>
 */
Map<Class<?>, EventProducer> producersInListener = handlerFinder.findAllProducers(object);  
for (Map.Entry<Class<?>, EventProducer> entry : producersInListener.entrySet()) {  
    final Class<?> key = entry.getKey();

    /**
     * 拿到对应的 EventProducer
     * 这里只拿一个 又表明了:
     * 一个 object 只存在 一个 EventProducer
     * producer 表示 已缓存的 该 object 的 所有 EventProducer
     * value 表示 通过 Finder 找到的 所有 EventHandler
     */
    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?");
    }
    /**
     * 从 EventProducer 缓存Map里移除
     * 并调用 EventProducer.invalidate() 方法
     * 设置该 EventProducer 不合法
     */
    producersByType.remove(key).invalidate();
}
  • 1.通过 AnnotatedHandlerFinder 找到 @Subscribe 方法
  • 2.然后 HandlerFinder 经由找回来的封装成 Map<Class<?>, Set<EventHandler>> 集合
  • 3.遍历 Map<Class<?>, Set<EventHandler>> 集合,拿到Set<EventHandler>集合,查看是否存在该缓存。
  • 4.存在缓存,继续遍历 Set<EventHandler> 集合,拿到EventHandler。
  • 5.如果 缓存的 EventHandler,又存在 Finder 先查的 EventHandler 之中,标记为不合法。
  • 6.删除该 Set<EventHandler> 集合的缓存




post 实现

先讲讲,这里有个方法,作用是 一个类的所有父类,包括自己,存储为一个 Set 集合。 也是 otto 一个工具方法

getClassesFor

/**
 * 寻找一个类所有父类 包括自己 存为一个 Set 集合
 *
 * @param concreteClass concreteClass
 * @return Set<Class<?>>
 */
private Set<Class<?>> getClassesFor(Class<?> concreteClass) {  
    List<Class<?>> parents = new LinkedList<Class<?>>();
    Set<Class<?>> classes = new HashSet<Class<?>>();

    parents.add(concreteClass);

    while (!parents.isEmpty()) {
        Class<?> clazz = parents.remove(0);
        classes.add(clazz);

        Class<?> parent = clazz.getSuperclass();
        if (parent != null) {
            parents.add(parent);
        }
    }
    return classes;
}

接着说说 post 的实现具体流程:

  • 1.通过 flattenHierarchy 方法去处理改事件的家谱集合( 自己+父类的集合 ),返回一个 Set<Class<?>> 集合
  • 1.1.flattenHierarchy 方法先看看 flattenHierarchyCache 缓存里是否存在该事件的家谱集合( 自己+父类的集合 )
  • 1.2.flattenHierarchyCache 里存在该事件的缓存,直接返回
  • 1.3.flattenHierarchyCache 里不存在该事件的缓存,则调用 getClassesFor 去收集该类的家谱集合( 自己+父类的集合 ),缓存一份到 flattenHierarchyCache 中,再返回
  • 2.遍历这个 Set<Class<?>> 集合( 家谱集合 ),然后拿到该监听类的缓存 Set<EventHandler> 集合,再遍历 Set<EventHandler> 集合,进入的到 enqueueEvent 里用 事件 + EventHandler 包装成 EventWithHandler 对象,并且执行 入队 逻辑
  • 3.判断是否该事件没有订阅者,并不是 DeadEvent 事件。符合,就给发一个 DeadEvent 事件
  • 4.最后会溜达到 dispatchQueuedEvents 里处理事件队列
/**
 * 拿到 该事件 + 该事件所有父类 的Set集合
 */
Set<Class<?>> dispatchTypes = flattenHierarchy(event.getClass());

boolean dispatched = false;  
/**
 * 遍历该事件 + 该事件所有父类 的Set集合
 */
for (Class<?> eventType : dispatchTypes) {

    /**
     * 拿到 该 object 所有缓存 EventHandler
     */
    Set<EventHandler> wrappers = getHandlersForEventType(eventType);

    /**
     * 开始进入 遍历缓存的 EventHandler
     * 并处理事件
     * 进入 enqueueEvent 逻辑
     */
    if (wrappers != null && !wrappers.isEmpty()) {
        dispatched = true;
        for (EventHandler wrapper : wrappers) {
            /**
             * 事件 + EventHandler 包装成 EventWithHandler
             * 入队
             */
            enqueueEvent(event, wrapper);
        }
    }
}

/**
 * 根据上面的循环可知道
 * 如果 object 存在 一个 EventHandler
 * 并且 post 的 事件不是 DeadEvent
 * 就会执行一次 post(new DeadEvent(this, event))
 */
if (!dispatched && !(event instanceof DeadEvent)) {  
    post(new DeadEvent(this, event));
}

dispatchQueuedEvents();  




注释源码

注释源码