打开一看,原来相关代码并不多,下面看下细节

主要方法也就是注册,取消注册和发送事件,可以看到两个主要的变量就是subscribers和dispatcher

  public void register(Object object) {
subscribers.register(object);
}

首先看下注册类中做了什么,在下面的注册类中,可以看到首先调用了这个方法,对传入的listener类型,利用反射拿到信息

  /**
* Returns all subscribers for the given listener grouped by the type of event they subscribe to.
*/
private Multimap<Class<?>, Subscriber> findAllSubscribers(Object listener) {
Multimap<Class<?>, Subscriber> methodsInListener = HashMultimap.create();
Class<?> clazz = listener.getClass();
for (Method method : getAnnotatedMethods(clazz)) {
Class<?>[] parameterTypes = method.getParameterTypes();
Class<?> eventType = parameterTypes[0];
methodsInListener.put(eventType, Subscriber.create(bus, listener, method));
}
return methodsInListener;
}

debug下就清楚了

  /** Registers all subscriber methods on the given listener object. */
void register(Object listener) {
Multimap<Class<?>, Subscriber> listenerMethods = findAllSubscribers(listener); for (Entry<Class<?>, Collection<Subscriber>> entry : listenerMethods.asMap().entrySet()) {
Class<?> eventType = entry.getKey();
Collection<Subscriber> eventMethodsInListener = entry.getValue(); CopyOnWriteArraySet<Subscriber> eventSubscribers = subscribers.get(eventType); if (eventSubscribers == null) {
CopyOnWriteArraySet<Subscriber> newSet = new CopyOnWriteArraySet<>();
eventSubscribers =
MoreObjects.firstNonNull(subscribers.putIfAbsent(eventType, newSet), newSet);
} eventSubscribers.addAll(eventMethodsInListener);
}
}

注册后这里的订阅者会保存如下信息。

其次是分发

  public void post(Object event) {
Iterator<Subscriber> eventSubscribers = subscribers.getSubscribers(event);
if (eventSubscribers.hasNext()) {
dispatcher.dispatch(event, eventSubscribers);
} else if (!(event instanceof DeadEvent)) {
// the event had no subscribers and was not itself a DeadEvent
post(new DeadEvent(this, event));
}
}

可见是先拿注册信息,再分发

    @Override
void dispatch(Object event, Iterator<Subscriber> subscribers) {
checkNotNull(event);
checkNotNull(subscribers);
Queue<Event> queueForThread = queue.get();
queueForThread.offer(new Event(event, subscribers)); if (!dispatching.get()) {
dispatching.set(true);
try {
Event nextEvent;
while ((nextEvent = queueForThread.poll()) != null) {
while (nextEvent.subscribers.hasNext()) {
nextEvent.subscribers.next().dispatchEvent(nextEvent.event);
}
}
} finally {
dispatching.remove();
queue.remove();
}
}
}

这里的dispatch通过反射执行

  /** Dispatches {@code event} to this subscriber using the proper executor. */
final void dispatchEvent(final Object event) {
executor.execute(
new Runnable() {
@Override
public void run() {
try {
invokeSubscriberMethod(event);
} catch (InvocationTargetException e) {
bus.handleSubscriberException(e.getCause(), context(event));
}
}
});
}

再下级

  /**
* Invokes the subscriber method. This method can be overridden to make the invocation
* synchronized.
*/
@VisibleForTesting
void invokeSubscriberMethod(Object event) throws InvocationTargetException {
try {
method.invoke(target, checkNotNull(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;
}
}

至此结束调用,这种设计还蛮特别的,值得学习

EventBus 源码学习的更多相关文章

  1. Java集合专题总结(1):HashMap 和 HashTable 源码学习和面试总结

    2017年的秋招彻底结束了,感觉Java上面的最常见的集合相关的问题就是hash--系列和一些常用并发集合和队列,堆等结合算法一起考察,不完全统计,本人经历:先后百度.唯品会.58同城.新浪微博.趣分 ...

  2. jQuery源码学习感想

    还记得去年(2015)九月份的时候,作为一个大四的学生去参加美团霸面,结果被美团技术总监教育了一番,那次问了我很多jQuery源码的知识点,以前虽然喜欢研究框架,但水平还不足够来研究jQuery源码, ...

  3. MVC系列——MVC源码学习:打造自己的MVC框架(四:了解神奇的视图引擎)

    前言:通过之前的三篇介绍,我们基本上完成了从请求发出到路由匹配.再到控制器的激活,再到Action的执行这些个过程.今天还是趁热打铁,将我们的View也来完善下,也让整个系列相对完整,博主不希望烂尾. ...

  4. MVC系列——MVC源码学习:打造自己的MVC框架(三:自定义路由规则)

    前言:上篇介绍了下自己的MVC框架前两个版本,经过两天的整理,版本三基本已经完成,今天还是发出来供大家参考和学习.虽然微软的Routing功能已经非常强大,完全没有必要再“重复造轮子”了,但博主还是觉 ...

  5. MVC系列——MVC源码学习:打造自己的MVC框架(二:附源码)

    前言:上篇介绍了下 MVC5 的核心原理,整篇文章比较偏理论,所以相对比较枯燥.今天就来根据上篇的理论一步一步进行实践,通过自己写的一个简易MVC框架逐步理解,相信通过这一篇的实践,你会对MVC有一个 ...

  6. MVC系列——MVC源码学习:打造自己的MVC框架(一:核心原理)

    前言:最近一段时间在学习MVC源码,说实话,研读源码真是一个痛苦的过程,好多晦涩的语法搞得人晕晕乎乎.这两天算是理解了一小部分,这里先记录下来,也给需要的园友一个参考,奈何博主技术有限,如有理解不妥之 ...

  7. 我的angularjs源码学习之旅2——依赖注入

    依赖注入起源于实现控制反转的典型框架Spring框架,用来削减计算机程序的耦合问题.简单来说,在定义方法的时候,方法所依赖的对象就被隐性的注入到该方法中,在方法中可以直接使用,而不需要在执行该函数的时 ...

  8. EventBus源码解析 源码阅读记录

    EventBus源码阅读记录 repo地址: greenrobot/EventBus EventBus的构造 双重加锁的单例. static volatile EventBus defaultInst ...

  9. ddms(基于 Express 的表单管理系统)源码学习

    ddms是基于express的一个表单管理系统,今天抽时间看了下它的代码,其实算不上源码学习,只是对它其中一些小的开发技巧做一些记录,希望以后在项目开发中能够实践下. 数据层封装 模块只对外暴露mod ...

随机推荐

  1. YzmCMSV3.1 | 代码审计

    YzmCMSV3.1 | 代码审计 这次审计 yzmcms . YzmCMS采用OOP(面向对象)方式自主开发的框架.框架易扩展,是一款高效开源的内容管理系统,产品基于PHP+Mysql架构,可运行在 ...

  2. ORA-22922: 不存在的 LOB 值 可以使用外层嵌套wm_concat()解决

    select kw0408id, sjbh, ksrs, kch, to_char(wm_concat(kcmc)) as kcmc, ksxs, kssc, ksfs, kcxz, xsyx, nj ...

  3. C# 生成日期维度值

    1. 时间维度表结构 /*==============================================================*/ /* Table: dim_date_day ...

  4. delphi WebBrowser的使用方法详解(六)

    通篇引用mshtml; 一.webbrowser获取滚动条的位置 function GetScrollPositionX(FWB:TEmbeddedWB):Integer;     //水平滚动条位置 ...

  5. ubuntu下 net core 安装web模板

    ---恢复内容开始--- 今天想试试在Linux用C#开发WebAPI,查了下,要用: dotnet new -t Web 来建立工程,结果我试了下,出来这段: Invalid input switc ...

  6. [TJOI2015]弦论(后缀自动机)

    /* 一道在树上乱搞的题目 建立出parent树来, 然后就能搞出每个节点往后能扩展出几个串, 至于位置不同算同一个的话就强制让right集合大小为1即可 然后在树上类比权值线段树找第k大26分统计一 ...

  7. ajax事件执行顺序

    1.ajaxStart(全局事件) 2.beforeSend 3.ajaxSend(全局事件) 4.success(请求成功时调用) 5.ajaxSuccess(全局事件) 6.error 7.aja ...

  8. c#,Model 实体转json,字符串转json

    public class JsonF { #region 字符串转json /// <summary> /// 字符串转json /// </summary> /// < ...

  9. Mac安装compass失败的原因

    之前一直用的windows电脑,突然间切换成mac,各种不习惯,刚开始的时候连文件夹都找不到,悲催…… 还好,熟悉了两天之后,基本上也能够操作了. 然后就是安装各种开发软件,由于个人习惯了使用sass ...

  10. Linux free -m 详解命令

    如下显示free是显示的当前内存的使用,-m的意思是M字节来显示内容.我们来一起看看. 1 2 3 4 5 6 $ free -m                total       used    ...