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