Otto是Square公司推出的事件总线库,目的是当你应用里的不同部分需要进行通讯时进行解耦。
使用方法
Otto的使用方法非常简单,有很多中文资料都有对其的入门介绍,如果英文不错,可以直接看官方文档
源码分析
UML类图
UML类图.png源码分析
Otto的原理就是使用反射完成方法的调用。
Bus构造函数
//用来区分事件总线,默认值是“default”
private final String identifier;
//用于注册,取消,发送事件的线程执行者,默认值是ThreadEnforcer.MAIN,即主线程
private final ThreadEnforcer enforcer;
//用户查找在注册和取消中的处理方法,默认值是HandlerFinder.ANNOTATED
private final HandlerFinder handlerFinder;
public Bus() {
this(DEFAULT_IDENTIFIER);
}
public Bus(String identifier) {
this(ThreadEnforcer.MAIN, identifier);
}
public Bus(ThreadEnforcer enforcer) {
this(enforcer, DEFAULT_IDENTIFIER);
}
public Bus(ThreadEnforcer enforcer, String identifier) {
this(enforcer, identifier, HandlerFinder.ANNOTATED);
}
Bus(ThreadEnforcer enforcer, String identifier, HandlerFinder handlerFinder) {
this.enforcer = enforcer;
this.identifier = identifier;
this.handlerFinder = handlerFinder;
}
register
public void register(Object object) {
if (object == null) {
throw new NullPointerException("Object to register must not be null.");
}
//判断是否在配置的线程内部进行事件发送,默认是主线程
enforcer.enforce(this);
//找到所有的Producers
Map<Class<?>, EventProducer> foundProducers = handlerFinder.findAllProducers(object);
for (Class<?> type : foundProducers.keySet()) {
final EventProducer producer = foundProducers.get(type);
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() + ".");
}
Set<EventHandler> handlers = handlersByType.get(type);
if (handlers != null && !handlers.isEmpty()) {
for (EventHandler handler : handlers) {
//处理Producer
dispatchProducerResultToHandler(handler, producer);
}
}
}
//找到所有的Subscribers
Map<Class<?>, Set<EventHandler>> foundHandlersMap = handlerFinder.findAllSubscribers(object);
for (Class<?> type : foundHandlersMap.keySet()) {
Set<EventHandler> handlers = handlersByType.get(type);
if (handlers == null) {
//如果不存在,则并发存储
Set<EventHandler> handlersCreation = new CopyOnWriteArraySet<EventHandler>();
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.");
}
}
for (Map.Entry<Class<?>, Set<EventHandler>> entry : foundHandlersMap.entrySet()) {
Class<?> type = entry.getKey();
EventProducer producer = producersByType.get(type);
if (producer != null && producer.isValid()) {
Set<EventHandler> foundHandlers = entry.getValue();
for (EventHandler foundHandler : foundHandlers) {
//如果producer无效
if (!producer.isValid()) {
break;
}
if (foundHandler.isValid()) {
//处理Producer
dispatchProducerResultToHandler(foundHandler, producer);
}
}
}
}
}
findAllSubscribers
static Map<Class<?>, Set<EventHandler>> findAllSubscribers(Object listener) {
Class<?> listenerClass = listener.getClass();
Map<Class<?>, Set<EventHandler>> handlersInMethod = new HashMap<Class<?>, Set<EventHandler>>();
//从Subscribers内存缓存中读取methods
Map<Class<?>, Set<Method>> methods = SUBSCRIBERS_CACHE.get(listenerClass);
if (null == methods) {
methods = new HashMap<Class<?>, Set<Method>>();
//使用注释加载Subscriber Methods
loadAnnotatedSubscriberMethods(listenerClass, methods);
}
if (!methods.isEmpty()) {
for (Map.Entry<Class<?>, Set<Method>> e : methods.entrySet()) {
Set<EventHandler> handlers = new HashSet<EventHandler>();
for (Method m : e.getValue()) {
//新增所有的EventHandler
handlers.add(new EventHandler(listener, m));
}
//以Class作为Key保存EventHandler集合
handlersInMethod.put(e.getKey(), handlers);
}
}
return handlersInMethod;
}
}
private static void loadAnnotatedSubscriberMethods(Class<?> listenerClass,
Map<Class<?>, Set<Method>> subscriberMethods) {
Map<Class<?>, Method> producerMethods = new HashMap<Class<?>, Method>();
loadAnnotatedMethods(listenerClass, producerMethods, subscriberMethods);
}
private static void loadAnnotatedMethods(Class<?> listenerClass,
Map<Class<?>, Method> producerMethods, Map<Class<?>, Set<Method>> subscriberMethods) {
for (Method method : listenerClass.getDeclaredMethods()) {
//判断该method是否是桥接模式,因为在编译过程中,有时候会动态产生桥接方法
if (method.isBridge()) {
continue;
}
//如果是Subscribe注释
if (method.isAnnotationPresent(Subscribe.class)) {
Class<?>[] parameterTypes = method.getParameterTypes();
//判断参数数量是否是1
if (parameterTypes.length != 1) {
throw new IllegalArgumentException("Method " + method + " has @Subscribe annotation but requires "
+ parameterTypes.length + " arguments. Methods must require a single argument.");
}
Class<?> eventType = parameterTypes[0];
//判断第一个参数是不是接口
if (eventType.isInterface()) {
throw new IllegalArgumentException("Method " + method + " has @Subscribe annotation on " + eventType
+ " which is an interface. Subscription must be on a concrete class type.");
}
//判断方法访问权限是否是Public
if ((method.getModifiers() & Modifier.PUBLIC) == 0) {
throw new IllegalArgumentException("Method " + method + " has @Subscribe annotation on " + eventType
+ " but is not 'public'.");
}
Set<Method> methods = subscriberMethods.get(eventType);
if (methods == null) {
methods = new HashSet<Method>();
subscriberMethods.put(eventType, methods);
}
methods.add(method);
}
//如果是Produce注释
else if (method.isAnnotationPresent(Produce.class)) {
Class<?>[] parameterTypes = method.getParameterTypes();
//判断参数数量是否是0
if (parameterTypes.length != 0) {
throw new IllegalArgumentException("Method " + method + "has @Produce annotation but requires "
+ parameterTypes.length + " arguments. Methods must require zero arguments.");
}
//判断返回值是否是Void
if (method.getReturnType() == Void.class) {
throw new IllegalArgumentException("Method " + method
+ " has a return type of void. Must declare a non-void type.");
}
Class<?> eventType = method.getReturnType();
//判断返回类型是否是接口
if (eventType.isInterface()) {
throw new IllegalArgumentException("Method " + method + " has @Produce annotation on " + eventType
+ " which is an interface. Producers must return a concrete class type.");
}
//判断返回值是否是Void
if (eventType.equals(Void.TYPE)) {
throw new IllegalArgumentException("Method " + method + " has @Produce annotation but has no return type.");
}
//判断方法访问权限是否是Public
if ((method.getModifiers() & Modifier.PUBLIC) == 0) {
throw new IllegalArgumentException("Method " + method + " has @Produce annotation on " + eventType
+ " but is not 'public'.");
}
//判断producerMethods里的eventType是否存在
if (producerMethods.containsKey(eventType)) {
throw new IllegalArgumentException("Producer for type " + eventType + " has already been registered.");
}
producerMethods.put(eventType, method);
}
}
//对producer和subscriber进行缓存
PRODUCERS_CACHE.put(listenerClass, producerMethods);
SUBSCRIBERS_CACHE.put(listenerClass, subscriberMethods);
}
findAllProducers和findAllSubscriber类似
unregister
public void unregister(Object object) {
if (object == null) {
throw new NullPointerException("Object to unregister must not be null.");
}
//判断是否在配置的线程内部进行事件发送,默认是主线程
enforcer.enforce(this);
Map<Class<?>, EventProducer> producersInListener = handlerFinder.findAllProducers(object);
for (Map.Entry<Class<?>, EventProducer> entry : producersInListener.entrySet()) {
final Class<?> key = entry.getKey();
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?");
}
//移除producersByType里内容,并且将其置成无效
producersByType.remove(key).invalidate();
}
Map<Class<?>, Set<EventHandler>> handlersInListener = handlerFinder.findAllSubscribers(object);
for (Map.Entry<Class<?>, Set<EventHandler>> entry : handlersInListener.entrySet()) {
Set<EventHandler> currentHandlers = getHandlersForEventType(entry.getKey());
Collection<EventHandler> eventMethodsInListener = entry.getValue();
if (currentHandlers == null || !currentHandlers.containsAll(eventMethodsInListener)) {
throw new IllegalArgumentException(
"Missing event handler for an annotated method. Is " + object.getClass()
+ " registered?");
}
for (EventHandler handler : currentHandlers) {
if (eventMethodsInListener.contains(handler)) {
//置成无效
handler.invalidate();
}
}
//移除currentHandlers里内容
currentHandlers.removeAll(eventMethodsInListener);
}
}
post
public void post(Object event) {
if (event == null) {
throw new NullPointerException("Event to post must not be null.");
}
enforcer.enforce(this);
//获取class集合,包括其父类
Set<Class<?>> dispatchTypes = flattenHierarchy(event.getClass());
boolean dispatched = false;
for (Class<?> eventType : dispatchTypes) {
//根据class获取EventHandler集合
Set<EventHandler> wrappers = getHandlersForEventType(eventType);
if (wrappers != null && !wrappers.isEmpty()) {
dispatched = true;
for (EventHandler wrapper : wrappers) {
//将事件插入队列
enqueueEvent(event, wrapper);
}
}
}
if (!dispatched && !(event instanceof DeadEvent)) {
post(new DeadEvent(this, event));
}
//派遣事件队列
dispatchQueuedEvents();
}
protected void dispatchQueuedEvents() {
//如果处于派遣中,则得到本次派遣结束后再派遣
if (isDispatching.get()) {
return;
}
isDispatching.set(true);
try {
while (true) {
//循环获取需要派遣的事件
EventWithHandler eventWithHandler = eventsToDispatch.get().poll();
//如果没有,则退出
if (eventWithHandler == null) {
break;
}
//如果事件有效,则进行派遣
if (eventWithHandler.handler.isValid()) {
dispatch(eventWithHandler.event, eventWithHandler.handler);
}
}
} finally {
isDispatching.set(false);
}
}
protected void dispatch(Object event, EventHandler wrapper) {
try {
wrapper.handleEvent(event);
} catch (InvocationTargetException e) {
throwRuntimeException(
"Could not dispatch event: " + event.getClass() + " to handler " + wrapper, e);
}
}
public void handleEvent(Object event) throws InvocationTargetException {
if (!valid) {
throw new IllegalStateException(toString() + " has been invalidated and can no longer handle events.");
}
try {
//利用反射执行目标函数
method.invoke(target, event);
} catch (IllegalAccessException e) {
throw new AssertionError(e);
} catch (InvocationTargetException e) {
if (e.getCause() instanceof Error) {
throw (Error) e.getCause();
}
throw e;
}
}
参考资料
可以随意转发,也欢迎关注我的简书,我会坚持给大家带来分享。
网友评论