EventBus原理

EventBus實現了觀察者模式,使用方法很是簡單,可參考:有用的Guava(二)segmentfault

這篇文章主要講解EventBus的實現原理。
一言以蔽之:EventBus內部有一個map,當register時往map中增長一個元素(key爲事件的類型,value爲觀察者),post時根據事件類型找到觀察者以後,對其反射調用。
下面咱們從register方法開始:安全

public void register(Object object) {
    Multimap<Class<?>, EventHandler> methodsInListener =
        finder.findAllHandlers(object);
    handlersByTypeLock.writeLock().lock();
    try {
      handlersByType.putAll(methodsInListener);
    } finally {
      handlersByTypeLock.writeLock().unlock();
    }
  }

調用eventBus.register(new Event())時,會將事件類型及觀察者(封裝爲EventHandler)放置在SetMultimap<Class<?>, EventHandler> handlersByType中,這是一個線程安全的對象容器,卸載事件也是在這個容器中作移除操做。根據事件類型查找觀察者時使用了策略模式,HandlerFindingStrategy finder作爲策略接口,目前只有一個策略實現AnnotatedHandlerFinder(查找帶有Subscribe註解的方法)。
有了這樣一個map,調用post時只須要根據類型找到觀察者就好了:app

public void post(Object event) {
    Set<Class<?>> dispatchTypes = flattenHierarchy(event.getClass());

    boolean dispatched = false;
    for (Class<?> eventType : dispatchTypes) {
      handlersByTypeLock.readLock().lock();
      try {
        Set<EventHandler> wrappers = handlersByType.get(eventType);

        if (!wrappers.isEmpty()) {
          dispatched = true;
          for (EventHandler wrapper : wrappers) {
            enqueueEvent(event, wrapper);
          }
        }
      } finally {
        handlersByTypeLock.readLock().unlock();
      }
    }

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

    dispatchQueuedEvents();
  }

這裏查找到參數匹配的EventHandler後並無馬上執行反射調用,而是分發到了事件隊列(ThreadLocal<Queue<EventWithHandler>> eventsToDispatch)中,當全部事件分發完畢以後,事件隊列作統一的事件消費。post

相關文章
相關標籤/搜索