对于一个对象,若是它能产生或处理某一类型的事件,则须要将其记录起来,Otto经过HandlerFinder工具类识别这种对象。java
首先看HandlerFinder接口:ide
interface HandlerFinder { Map<Class<?>, EventProducer> findAllProducers(Object listener); Map<Class<?>, Set<EventHandler>> findAllSubscribers(Object listener); HandlerFinder ANNOTATED = new HandlerFinder() { @Override public Map<Class<?>, EventProducer> findAllProducers(Object listener) { return AnnotatedHandlerFinder.findAllProducers(listener); } @Override public Map<Class<?>, Set<EventHandler>> findAllSubscribers(Object listener) { return AnnotatedHandlerFinder.findAllSubscribers(listener); } }; }
这个接口定义了两个方法来查找给定对象的事件产生方法与监听方法。对于找到的事件产生对象保存在一个map里, map的key是事件的类型, value是一个包装对象EventProducer, 从这里能够看出,对于一种事件类型,一个对象最多容许有一个事件产生方法; 对于事件监听, 一个对象则能够有多个方法对同一类型事件进行监听。工具
上述HandlerFinder接口在功能上实际是由AnnotatedHandlerFinder实现的(虽然没显示implement);spa
PRODUCER_CACHE 的类型是这样的 Map<ProducerClass, Map<事件类型, 方法> > , code
SUBSCRIBER_CACHE的类型: Map< SubscriberClass, Map< 事件类型,Set<方法> > >. 对象
由于一个类对某一类型事件只能有一个产生方法, 可是,一个类对某一类型事件能够有多个监听方法。接口
loadAnnotatedMethods(Class<?> )扫描一个类,将其带有标注的方法及对应的事件类型放入相应的cache。事件
注意区分listener 与listenerClass, 前者是一个普通的对象, 后者是listener的 类型(Class)。get
final class AnnotatedHandlerFinder { private static final Map<Class<?>, Map<Class<?>, Method>> PRODUCERS_CACHE = new HashMap<Class<?>, Map<Class<?>, Method>>(); private static final Map<Class<?>, Map<Class<?>, Set<Method>>> SUBSCRIBERS_CACHE = new HashMap<Class<?>, Map<Class<?>, Set<Method>>>(); static Map<Class<?>, EventProducer> findAllProducers(Object listener) { final Class<?> listenerClass = listener.getClass(); Map<Class<?>, EventProducer> handlersInMethod = new HashMap<Class<?>, EventProducer>(); if (!PRODUCERS_CACHE.containsKey(listenerClass)) { loadAnnotatedMethods(listenerClass); } Map<Class<?>, Method> methods = PRODUCERS_CACHE.get(listenerClass); if (!methods.isEmpty()) { for (Map.Entry<Class<?>, Method> e : methods.entrySet()) { EventProducer producer = new EventProducer(listener, e.getValue()); handlersInMethod.put(e.getKey(), producer); } } return handlersInMethod; } /** This implementation finds all methods marked with a {@link Subscribe} annotation. */ static Map<Class<?>, Set<EventHandler>> findAllSubscribers(Object listener) { Class<?> listenerClass = listener.getClass(); Map<Class<?>, Set<EventHandler>> handlersInMethod = new HashMap<Class<?>, Set<EventHandler>>(); if (!SUBSCRIBERS_CACHE.containsKey(listenerClass)) { loadAnnotatedMethods(listenerClass); } Map<Class<?>, Set<Method>> methods = SUBSCRIBERS_CACHE.get(listenerClass); if (!methods.isEmpty()) { for (Map.Entry<Class<?>, Set<Method>> e : methods.entrySet()) { Set<EventHandler> handlers = new HashSet<EventHandler>(); for (Method m : e.getValue()) { handlers.add(new EventHandler(listener, m)); } handlersInMethod.put(e.getKey(), handlers); } } return handlersInMethod; }