前言
EventBus的核心思想是觀察者模式 (生產/消費者編程模型) 。html
經過前面的文章咱們已經知道,如何使用eventBus了。咱們須要先定義一個Observer(前文中的EventListener類),而後將其註冊到eventBus裏,經過 @Subscribe 定義消息回調函數。dom
那咱們先看看register(Object object) 和unregister(Object object) 方法。函數
register (Object object) 解析
1
2
3
4
5
6
7
8
9
10
|
public void register(Object object) {
Multimap<Class<?>, EventSubscriber> methodsInListener =
finder.findAllSubscribers(object);
subscribersByTypeLock.writeLock().lock();
try {
subscribersByType.putAll(methodsInListener);
} finally {
subscribersByTypeLock.writeLock().unlock();
}
}
|
能夠看到是先經過SubscriberFindingStrategy接口裏的findAllSubscribers方法獲取全部標記了@ Subscribe 註解的方法,其中該接口的具體實現是AnnotatedSubscriberFinder類。放到一個guava裏定義的Multimap裏。而後是把獲取到的methodsInListener放到一個叫subscribersByType的 guava裏定義的SetMultimap裏 。post
1
2
3
4
5
6
7
8
9
10
11
|
public Multimap<Class<?>, EventSubscriber> findAllSubscribers(Object listener) {
Multimap<Class<?>, EventSubscriber> methodsInListener = HashMultimap.create();
Class<?> clazz = listener.getClass();
for (Method method : getAnnotatedMethods(clazz)) {
Class<?>[] parameterTypes = method.getParameterTypes();
Class<?> eventType = parameterTypes[0];
EventSubscriber subscriber = makeSubscriber(listener, method);
methodsInListener.put(eventType, subscriber);
}
return methodsInListener;
}
|
findAllSubscribers方法裏,最重要的是methodsInListener,它的結構能夠簡單理解爲一個map,其中key是eventType,在我前文寫的例子中就是com.sww.eventbus.domain.MessageEvent,其中value是subscriber,就是例子中的com.sww.eventbus.listener.EventListener#onMessageEvent。this
總之,一句話就是先經過標記找到全部已經註冊進來的觀察者,而後存放到容器裏備用。spa
那unregister就是從容器刪除它們,code
unRegister (Object object) 解析
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
public void unregister(Object object) {
Multimap<Class<?>, EventSubscriber> methodsInListener = finder.findAllSubscribers(object);
for (Entry<Class<?>, Collection<EventSubscriber>> entry :
methodsInListener.asMap().entrySet()) {
Class<?> eventType = entry.getKey();
Collection<EventSubscriber> eventMethodsInListener = entry.getValue();
subscribersByTypeLock.writeLock().lock();
try {
Set<EventSubscriber> currentSubscribers = subscribersByType.get(eventType);
if (!currentSubscribers.containsAll(eventMethodsInListener)) {
throw new IllegalArgumentException(
"missing event subscriber for an annotated method. Is " + object + " registered?");
}
currentSubscribers.removeAll(eventMethodsInListener);
} finally {
subscribersByTypeLock.writeLock().unlock();
}
}
}
|
post( Object event)解析
有了觀察者,下面就是發送事件了,閱讀過前文會知道是經過eventBus.post(Object event)來發送事件消息。那我們來看看這個post方法。server
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
public void post(Object event) {
Set<Class<?>> dispatchTypes = flattenHierarchy(event.getClass());
boolean dispatched = false;
for (Class<?> eventType : dispatchTypes) {
subscribersByTypeLock.readLock().lock();
try {
Set<EventSubscriber> wrappers = subscribersByType.get(eventType);
if (!wrappers.isEmpty()) {
dispatched = true;
for (EventSubscriber wrapper : wrappers) {
enqueueEvent(event, wrapper);
}
}
} finally {
subscribersByTypeLock.readLock().unlock();
}
}
if (!dispatched && !(event instanceof DeadEvent)) {
post(new DeadEvent(this, event));
}
dispatchQueuedEvents();
}
|
該方法就是從以前的容器subscribersByType裏獲取到eventType對應的觀察者,而後組裝成EventWithSubscriber放到隊列裏。
1
2
3
|
void enqueueEvent(Object event, EventSubscriber subscriber) {
eventsToDispatch.get().offer(new EventWithSubscriber(event, subscriber));
}
|
而後就是最後的dispatchQueuedEvents(),通過一層層深刻進去,能夠發現wrapper.handleEvent(event),其中 handleEvent方法就是最終的關鍵了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public void handleEvent(Object event) throws InvocationTargetException {
checkNotNull(event);
try {
method.invoke(target, new Object[] { event });
} catch (IllegalArgumentException e) {
throw new Error("Method rejected target/argument: " + event, e);
} catch (IllegalAccessException e) {
throw new Error("Method became inaccessible: " + event, e);
} catch (InvocationTargetException e) {
if (e.getCause() instanceof Error) {
throw (Error) e.getCause();
}
throw e;
}
}
|
就是經過Java的反射機制實現。
須要說明的是,若是沒有訂閱者註冊到要發送的event事件上,而且該event不是DeadEvent,那麼它將被包裝成DeadEvent中並從新發布。也就是其中這三行代碼索要作的
1
2
3
|
if (!dispatched && !(event instanceof DeadEvent)) {
post(new DeadEvent(this, event));
}
|