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的更多相关文章

  1. Guava - EventBus(事件总线)

    Guava在guava-libraries中为我们提供了事件总线EventBus库,它是事件发布订阅模式的实现,让我们能在领域驱动设计(DDD)中以事件的弱引用本质对我们的模块和领域边界很好的解耦设计 ...

  2. 设计模式:Observer(观察者)—— Guava EventBus

    本文分为三个部分:   Observer(观察者) Guava EventBus详解 Guava EventBus使用示例   1. Observer(观察者)   1.1 背景   我们设计系统时, ...

  3. Guava 12:Guava EventBus源码剖析

    一.架构速读 传统上,Java的进程内事件分发都是通过发布者和订阅者之间的显式注册实现的.设计EventBus就是为了取代这种显示注册方式,使组件间有了更好的解耦.EventBus不是通用型的发布-订 ...

  4. 使用Guava EventBus构建publish/subscribe系统

    Google的Guava类库提供了EventBus,用于提供一套组件内publish/subscribe的解决方案.事件总线EventBus,用于管理事件的注册和分发.在系统中,Subscribers ...

  5. 观察者模式与Guava EventBus

    观察者模式 结构图 代码实现 public abstract class Subject { private List<Observer> observerList = new Array ...

  6. Guava ---- EventBus事件驱动模型

    在软件开发过程中, 难免有信息的共享或者对象间的协作. 怎样让对象间信息共享高效, 而且耦合性低. 这是一个难题. 而耦合性高将带来编码改动牵一发而动全身的连锁效应. Spring的风靡正是由于攻克了 ...

  7. guava eventbus 原理+源码分析

    前言: guava提供的eventbus可以很方便的处理一对多的事件问题, 最近正好使用到了,做个小结,使用的demo网上已经很多了,不再赘述,本文主要是源码分析+使用注意点+新老版本eventbus ...

  8. 观察者模式与Google Guava EventBus实现

    概述 观察者模式又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种. 它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态变化时,会 ...

  9. guava EventBus 消息总线的运用

    public class Test { public static void main(String[] args) { final EventBus eventBus = new EventBus( ...

随机推荐

  1. 用淘宝镜像cnpm代替npm

    安装淘宝镜像cnpm: $ sudo npm install -g cnpm --registry=https://registry.npm.taobao.org 然后就大部分可以用cnpm来代替np ...

  2. 【转载】“惊群”,看看nginx是怎么解决它的

    原文:http://blog.csdn.net/russell_tao/article/details/7204260 在说nginx前,先来看看什么是“惊群”?简单说来,多线程/多进程(linux下 ...

  3. bzoj 1407 扩展欧几里德

    思路:枚举洞穴个数,用扩展欧几里德暴力判断没两个人的周期. #include<bits/stdc++.h> #define LL long long #define fi first #d ...

  4. 8种json数据查询方式

    你有没有对“在复杂的JSON数据结构中查找匹配内容”而烦恼.这里有8种不同的方式可以做到: JsonSQL JsonSQL实现了使用SQL select语句在json数据结构中查询的功能. 例子: ? ...

  5. java线程基本知识

    如何去定义一个线程?(三种方式)    1.Thread:继承这个类,然后重写run方法:将业务逻辑或任务写到run方法中,然后调用start来启动线程:    2.Runnable: 实现这个接口, ...

  6. shopnc 店铺二级分类添加商品

    $class_2 = $goods_class[$gc_id]['gc_parent_id']; $class_1 = $goods_class[$class_2]['gc_parent_id']; ...

  7. ZOJ 3211 Dream City

    贪心,$dp$. 假设我们知道要选择哪些物品,那么这些物品应该按什么顺序选择呢? 物品$A(a1,b1)$,物品$B(a2,b3)$. 假设物品$A$在第$x$天被选择,物品$B$在第$y$天被选择. ...

  8. Knockout.js(一):简介

    Knockout是一款很优秀的JavaScript库,通过应用MVVM模式使JavaScript前端UI简单化.任何时候你的局部UI内容需要自动更新,KO都可以很简单的帮你实现,并且非常易于维护. K ...

  9. Spring 异常

    Java Web项目整体异常处理机制   http://www.51testing.com/html/90/n-823590.html spring mvc 异常统一处理方式 http://www.c ...

  10. 【hdu1280】前M大的数

    前m大的数 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submi ...