前言
EventBus的核心思想是觀察者模式 (生產/消費者編程模型) 。
通過前面的文章我們已經知道,如何使用eventBus了。我們需要先定義一個Observer(前文中的EventListener類),然后將其注冊到eventBus里,通過 @Subscribe 定義消息回調函數。
那我們先看看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里 。
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。
總之,一句話就是先通過標記找到所有已經注冊進來的觀察者,然后存放到容器里備用。
那unregister就是從容器刪除它們,
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方法。
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));
}
|