52.otto 源码解析
Posted 初心始终钰
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了52.otto 源码解析相关的知识,希望对你有一定的参考价值。
otto 源码解析
Otto的源码非常简单,一共就九个类。
项目结构
- AnnotatedHandlerFinder ( 查找并缓存所有注解方法 )
- Bus ( otto核心业务类,包括注册、反注册、发送事件等等 )
- DeadEvent ( 内置事件,没有订阅者,不能被传递 )
- EventHandler ( 封装@Subscribe方法及其所在类 )
- EventProducer ( 封装@Produce方法及其所在类 )
- HandlerFinder ( 调用AnnotatedHandlerFinder的方法拿到注解方法,封装成EventHandler和EventProducer的集合 )
- Produce ( @Produce )
- Subscribe ( @Subscribe )
- ThreadEnforcer ( 用于切换线程 )
register 实现
处理 @Produce 逻辑
- 1.通过 AnnotatedHandlerFinder 找到 @Produce 方法
- 2.然后 HandlerFinder 经由找回来的封装成
Map<Class<?>, EventProducer>
集合 - 3.遍历
Map<Class<?>, EventProducer>
集合,逐个拿到该类对应的全部缓存的EventHandler - 4.这样就凑齐了@Subscribe 和 @Produce 方法
- 5.调用dispatchProducerResultToHandler处理:所谓的 提供 @Produce 被自身 @Subscribe 消费的流程
/**
* 通过HandlerFinder找到所有
* object里所有 @Produce 方法
* 找回来的封装成EventProducer
* 并且最后返回Map<Class<?>, EventProducer>
*/
Map<Class<?>, EventProducer> foundProducers = handlerFinder.findAllProducers(object);
for (Class<?> type : foundProducers.keySet()) {
/**
* 逐个拿到EventProducer
*/
final EventProducer producer = foundProducers.get(type);
/**
* ConcurrentMap putIfAbsent 安全的put
* 防止并发
* 查看缓存 ConcurrentMap<Class<?>, EventProducer> 有木有
*/
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() + ".");
}
/**
* 逐个拿到全部缓存EventHandler ( @Subscribe方法封装类 )
*/
Set<EventHandler> handlers = handlersByType.get(type);
if (handlers != null && !handlers.isEmpty()) {
for (EventHandler handler : handlers) {
/**
* 逐个去调用@Subscribe 和 @Produce 方法
*/
dispatchProducerResultToHandler(handler, producer);
}
}
}
处理 @SubScribe 逻辑
- 1.通过 AnnotatedHandlerFinder 找到 @Subscribe 方法
- 2.然后 HandlerFinder 经由找回来的封装成
Map<Class<?>, Set<EventHandler>>
集合 - 3.先遍历
Map<Class<?>, Set<EventHandler>>
集合,拿到Set<EventHandler>
刷新缓存 - 4.再次循环
Map<Class<?>, Set<EventHandler>>
集合,查找对应类的Set<EventProducer>
缓存。 - 6.调用dispatchProducerResultToHandler处理,再一次完成:所谓的 提供 @Produce 被自身 @Subscribe 消费的流程
/**
* 通过HandlerFinder找到所有
* object里所有 @SubScribe 方法
* 找回来的封装成EventHandler
* Map<Class<?>, Set<EventHandler>>
*/
Map<Class<?>, Set<EventHandler>> foundHandlersMap = handlerFinder.findAllSubscribers(object);
/**
* 逐个拿到EventHandler
*/
for (Class<?> type : foundHandlersMap.keySet()) {
/**
* 拿到缓存 EventHandler 集合
*/
Set<EventHandler> handlers = handlersByType.get(type);
if (handlers == null) {
//concurrent put if absent
Set<EventHandler> handlersCreation = new CopyOnWriteArraySet<EventHandler>();
/**
* 往缓存 EventHandler Map 里放入一份 type 对应的 EventHandle 集合
*/
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.");
}
}
/**
* 遍历所有找到 EventHandler ( @Subscribe方法 )
*/
for (Map.Entry<Class<?>, Set<EventHandler>> entry : foundHandlersMap.entrySet()) {
Class<?> type = entry.getKey();
/**
* 再拿一次 EventProducer 缓存
* 如果object 里 存在 @Producer 方法
* 才循环 EventHandler 的逻辑里去 调用
* dispatchProducerResultToHandler方法
*/
EventProducer producer = producersByType.get(type);
if (producer != null && producer.isValid()) {
Set<EventHandler> foundHandlers = entry.getValue();
for (EventHandler foundHandler : foundHandlers) {
if (!producer.isValid()) {
break;
}
if (foundHandler.isValid()) {
dispatchProducerResultToHandler(foundHandler, producer);
}
}
}
}
unregister 实现
- 1.通过 AnnotatedHandlerFinder 找到 @Produce 方法
- 2.然后 HandlerFinder 经由找回来的封装成
Map<Class<?>, EventProducer>
集合 - 3.遍历
Map<Class<?>, EventProducer>
集合,逐个拿到EventProducer,并去查找是否存在该EventProducer缓存。 - 4.存在缓存 ,从 EventProducer 缓存Map里移除,调用 EventProducer.invalidate()方法
/**
* 通过HandlerFinder找到所有
* object里所有 @Produce 方法
* 找回来的封装成EventProducer
* 并且最后返回Map<Class<?>, EventProducer>
*/
Map<Class<?>, EventProducer> producersInListener = handlerFinder.findAllProducers(object);
for (Map.Entry<Class<?>, EventProducer> entry : producersInListener.entrySet()) {
final Class<?> key = entry.getKey();
/**
* 拿到对应的 EventProducer
* 这里只拿一个 又表明了:
* 一个 object 只存在 一个 EventProducer
* producer 表示 已缓存的 该 object 的 所有 EventProducer
* value 表示 通过Finder 找到的 所有 EventHandler
*/
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?");
}
/**
* 从 EventProducer 缓存Map里移除
* 并调用 EventProducer.invalidate()方法
* 设置该 EventProducer 不合法
*/
producersByType.remove(key).invalidate();
}
- 1.通过 AnnotatedHandlerFinder 找到 @Subscribe 方法
- 2.然后 HandlerFinder 经由找回来的封装成
Map<Class<?>, Set<EventHandler>>
集合 - 3.遍历
Map<Class<?>, Set<EventHandler>>
集合,拿到Set<EventHandler>
集合,查看是否存在该缓存。 - 4.存在缓存,继续遍历
Set<EventHandler>
集合,拿到EventHandler。 - 5.如果 缓存的 EventHandler,又存在 Finder 先查的 EventHandler 之中,标记为不合法。
- 6.删除该
Set<EventHandler>
集合的缓存
post 实现
先讲讲,这里有个方法,作用是 一个类的所有父类,包括自己,存储为一个 Set 集合。
也是otto一个工具方法。
getClassesFor
/**
* 寻找一个类所有父类 包括自己 存为一个 Set 集合
*
* @param concreteClass concreteClass
* @return Set<Class<?>>
*/
private Set<Class<?>> getClassesFor(Class<?> concreteClass) {
List<Class<?>> parents = new LinkedList<Class<?>>();
Set<Class<?>> classes = new HashSet<Class<?>>();
parents.add(concreteClass);
while (!parents.isEmpty()) {
Class<?> clazz = parents.remove(0);
classes.add(clazz);
Class<?> parent = clazz.getSuperclass();
if (parent != null) {
parents.add(parent);
}
}
return classes;
}
接着说说 post 的实现具体流程:
- 1.通过
flattenHierarchy
方法去处理改事件的家谱集合( 自己+父类的集合 ),返回一个Set<Class<?>>
集合 - 1.1.
flattenHierarchy
方法先看看flattenHierarchyCache缓存里是否存在该事件的家谱集合( 自己+父类的集合 ) - 1.2.flattenHierarchyCache里存在该事件的缓存,直接返回
- 1.3.flattenHierarchyCache里不存在该事件的缓存,则调用
getClassesFor
去收集该类的家谱集合( 自己+父类的集合 ),缓存一份到flattenHierarchyCache中,再返回 - 2.遍历这个
Set<Class<?>>
集合( 家谱集合 ),然后拿到该监听类的缓存Set<EventHandler>
集合,再遍历Set<EventHandler>
集合,进入的到enqueueEvent
里用 事件 + EventHandler 包装成 EventWithHandler对象,并且执行入队逻辑 - 3.判断是否该事件没有订阅者,并不是DeadEvent事件。符合,就给发一个DeadEvent事件
- 4.最后会溜达到
dispatchQueuedEvents
里处理事件队列
/**
* 拿到 该事件 + 该事件所有父类 的Set集合
*/
Set<Class<?>> dispatchTypes = flattenHierarchy(event.getClass());
boolean dispatched = false;
/**
* 遍历该事件 + 该事件所有父类 的Set集合
*/
for (Class<?> eventType : dispatchTypes) {
/**
* 拿到 该 object 所有缓存 EventHandler
*/
Set<EventHandler> wrappers = getHandlersForEventType(eventType);
/**
* 开始进入 遍历缓存的 EventHandler
* 并处理事件
* 进入 enqueueEvent 逻辑
*/
if (wrappers != null && !wrappers.isEmpty()) {
dispatched = true;
for (EventHandler wrapper : wrappers) {
/**
* 事件 + EventHandler 包装成 EventWithHandler
* 入队
*/
enqueueEvent(event, wrapper);
}
}
}
/**
* 根据上面的循环可知道
* 如果 object 存在 一个 EventHandler
* 并且post的 事件不是 DeadEvent
* 就会执行一次 post(new DeadEvent(this, event))
*/
if (!dispatched && !(event instanceof DeadEvent)) {
post(new DeadEvent(this, event));
}
dispatchQueuedEvents();
注释源码
以上是关于52.otto 源码解析的主要内容,如果未能解决你的问题,请参考以下文章
片段(Java) | 机试题+算法思路+考点+代码解析 2023
Android 逆向类加载器 ClassLoader ( 类加载器源码简介 | BaseDexClassLoader | DexClassLoader | PathClassLoader )(代码片段
初识Spring源码 -- doResolveDependency | findAutowireCandidates | @Order@Priority调用排序 | @Autowired注入(代码片段
初识Spring源码 -- doResolveDependency | findAutowireCandidates | @Order@Priority调用排序 | @Autowired注入(代码片段