[Guava] EventBus
1. 发布-订阅模式
发布-订阅模式(publish-subscribe)是一种编程范式,发布方不发布消息给特定的接收方,而是由订阅方选择性接收。这使得发布方和订阅方相对独立,减少了耦合性。
在发布-订阅模式中,有以下几个难点:
1)如何区分或分配订阅者关注的消息;
2)发布者如何将消息提交给对应订阅者;
下图描述Guava EventBus对发布-订阅模式的实现。

2. 订阅者注册
下面是简单的订阅者实现:
// 订阅者
public class Subscriber {
@Subscribe
public void process(String event) {
System.out.print(event);
}
}
注册订阅者:
// 消息订阅
EventBus eventBus = new EventBus();
eventBus.register(new Subscriber());
Guava EventBus中有关注册的流程:

Guava EventBus中有关注册的代码:
// SubscriberRegistry.register()
void register(Object listener) {
// 查找订阅者中有Subscribe注解的方法
// findAllSubscribers返回值: 函数参数类型-{EventBus,listener,有Subscribe注解的方法}
Multimap<Class<?>, Subscriber> listenerMethods = findAllSubscribers(listener); for (Map.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<Subscriber>();
eventSubscribers = MoreObjects.firstNonNull(
subscribers.putIfAbsent(eventType, newSet), newSet);
} eventSubscribers.addAll(eventMethodsInListener);
}
}
3. 事件提交&处理
eventBus.post("Hello, EventBus");
Guava EventBus中消息提交和处理流程:

Guava EventBus中消息提交和处理代码:
// EventBus.post(..)
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));
}
}
Dispatcher有以下几种:
1. PerThreadQueuedDispatcher( EventBus默认分配类型) : 按照事件提交顺序进行处理(a breadth-first dispatch)。
2. LegacyAsyncDispatcher(AsyncEventBus默认分配类型):若订阅者处理函数上有AllowConcurrentEvents注解,则使用线程中对象进行多线程并行处理。
class Subscriber {
static Subscriber create(EventBus bus, Object listener, Method method) {
return method.getAnnotation(AllowConcurrentEvents.class) != null
? new Subscriber(bus, listener, method)
: new SynchronizedSubscriber(bus, listener, method);
}
}
Subscriber中dispatchEvent中处理方法:
final void dispatchEvent(final Object event) {
executor.execute(new Runnable() {
@Override
public void run() {
method.invoke(target, checkNotNull(event));
});
}
3. ImmediateDispatcher:立即将事件提交给对应的订阅者(a depth-first dispatch)
[Guava] EventBus的更多相关文章
- Guava - EventBus(事件总线)
Guava在guava-libraries中为我们提供了事件总线EventBus库,它是事件发布订阅模式的实现,让我们能在领域驱动设计(DDD)中以事件的弱引用本质对我们的模块和领域边界很好的解耦设计 ...
- 设计模式:Observer(观察者)—— Guava EventBus
本文分为三个部分: Observer(观察者) Guava EventBus详解 Guava EventBus使用示例 1. Observer(观察者) 1.1 背景 我们设计系统时, ...
- Guava 12:Guava EventBus源码剖析
一.架构速读 传统上,Java的进程内事件分发都是通过发布者和订阅者之间的显式注册实现的.设计EventBus就是为了取代这种显示注册方式,使组件间有了更好的解耦.EventBus不是通用型的发布-订 ...
- 使用Guava EventBus构建publish/subscribe系统
Google的Guava类库提供了EventBus,用于提供一套组件内publish/subscribe的解决方案.事件总线EventBus,用于管理事件的注册和分发.在系统中,Subscribers ...
- 观察者模式与Guava EventBus
观察者模式 结构图 代码实现 public abstract class Subject { private List<Observer> observerList = new Array ...
- Guava ---- EventBus事件驱动模型
在软件开发过程中, 难免有信息的共享或者对象间的协作. 怎样让对象间信息共享高效, 而且耦合性低. 这是一个难题. 而耦合性高将带来编码改动牵一发而动全身的连锁效应. Spring的风靡正是由于攻克了 ...
- guava eventbus 原理+源码分析
前言: guava提供的eventbus可以很方便的处理一对多的事件问题, 最近正好使用到了,做个小结,使用的demo网上已经很多了,不再赘述,本文主要是源码分析+使用注意点+新老版本eventbus ...
- 观察者模式与Google Guava EventBus实现
概述 观察者模式又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种. 它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态变化时,会 ...
- guava EventBus 消息总线的运用
public class Test { public static void main(String[] args) { final EventBus eventBus = new EventBus( ...
随机推荐
- FineReport——JS二次开发(分页预览)
BS访问某个cpt模板,报表servlet将会将cpt文件解析成对应的html,报表内容最终转换为一个table,位于id=content-container的div中. 在模板和html页面中,他们 ...
- 《java并发编程实战》读书笔记12--原子变量,非阻塞算法,CAS
第15章 原子变量与非阻塞同步机制 近年来,在并发算法领域的大多数研究都侧重于非阻塞算法,这种算法用底层的原子机器指令(例如比较并交换指令)代替锁老确保数据在并发访问中的一致性. 15.1 锁的劣势 ...
- poj 1742(好题,楼天城男人八题,混合背包)
Coins Time Limit: 3000MS Memory Limit: 30000K Total Submissions: 33269 Accepted: 11295 Descripti ...
- windows10 易升 下载失败 解决方法
在你剩余最大空间的硬盘里有一个名字大概是Windows10Updata的文件夹里找到一个名字14339开头的升级镜像,把这个文件的名字用记事本保存下来方便以后使用,同时在这个文件夹里还有一个叫prod ...
- CentOS7安装和配置vsftpd
(1)vsftpd基本介绍 作用:实现文件共享 1)vsftpd两种模式 主动模式 所谓主动模式,指的是FTP服务器"主动"去连接客户端的数据端口来传输数据,其过程具体来说就是:客 ...
- CentOS 7.4 上如何安装 tomcat 9
本文将详细讲解在 CentOS 7.4 系统上如何安装tomcat 9,tomcat是没有32位和64位之分的. 创建tomcat的安装路径 首先在/usr/local/下建立一个tomcat的文件夹 ...
- python+django+vue搭建前后端分离项目
以前一直是做基于PHP或JAVA的前后端分离开发,最近跟着python风搭建了一个基于django的前后端分享项目 准备工作:IDE,[JetBrains PyCharm2018][webpack 3 ...
- sql查询总结
1.SQL select 语句 SELECT 语句用于从表中选取数据. 结果被存储在一个结果表中(称为结果集). SELECT 列名称 FROM 表名称 实例: SELECT username,pas ...
- 洛谷P2783 有机化学之神偶尔会作弊
题目传送门 啦啦啦,发个文纪念一下第一道在洛谷上A的黑题,一次性就过真是无比舒服-(虽然某些大佬说这题有点水……)题目其实思路不难,Tarjan缩点+LCA,不过因为是无向边,所以在Tarjan的时候 ...
- SPOJ11469 Subset(折半枚举)
题意 给定一个集合,有多少个非空子集,能划分成和相等的两份.\(n\leq 20\) 题解 看到这个题,首先能想到的是\(3^n\)的暴力枚举,枚举当前元素是放入左边还是放入右边或者根本不放,但是显然 ...