EventBus是Guava的事件处理机制,是设计模式中的观察者模式(生产/消费者编程模型)的优雅实现。对于事件监听和发布订阅模式,EventBus是一个非常优雅和简单解决方案,我们不用创建复杂的类和接口层次结构。

  Observer模式是比较常用的设计模式之一,虽然有时候在具体代码里,它不一定叫这个名字,比如改头换面叫个Listener,但模式就是这个模式。手工实现一个Observer也不是多复杂的一件事,只是因为这个设计模式实在太常用了,Java就把它放到了JDK里面:Observable和Observer,从JDK 1.0里,它们就一直在那里。从某种程度上说,它简化了Observer模式的开发,至少我们不用再手工维护自己的Observer列表了。不过,如前所述,JDK里的Observer从1.0就在那里了,直到Java 7,它都没有什么改变,就连通知的参数还是Object类型。要知道,Java 5就已经泛型了。Java 5是一次大规模的语法调整,许多程序库从那开始重新设计了API,使其更简洁易用。当然,那些不做应对的程序库,多半也就过时了。这也就是这里要讨论知识更新的原因所在。今天,对于普通的应用,如果要使用Observer模式该如何做呢?答案是Guava的EventBus。

  EventBus基本用法:

  使用Guava之后, 如果要订阅消息, 就不用再继承指定的接口, 只需要在指定的方法上加上@Subscribe注解即可。代码如下:

  消息封装类:

public class TestEvent {
private final int message;
public TestEvent(int message) {
this.message = message;
System.out.println("event message:"+message);
}
public int getMessage() {
return message;
}
}

  消息接受类:

public class EventListener {
public int lastMessage = 0; @Subscribe
public void listen(TestEvent event) {
lastMessage = event.getMessage();
System.out.println("Message:"+lastMessage);
} public int getLastMessage() {
return lastMessage;
}
}

  测试类及输出结果:

public class TestEventBus {
@Test
public void testReceiveEvent() throws Exception { EventBus eventBus = new EventBus("test");
EventListener listener = new EventListener(); eventBus.register(listener); eventBus.post(new TestEvent(200));
eventBus.post(new TestEvent(300));
eventBus.post(new TestEvent(400)); System.out.println("LastMessage:"+listener.getLastMessage());
;
}
} //输出信息
event message:200
Message:200
event message:300
Message:300
event message:400
Message:400
LastMessage:400

  MultiListener的使用:

  只需要在要订阅消息的方法上加上@Subscribe注解即可实现对多个消息的订阅,代码如下:

public class MultipleListener {
public Integer lastInteger;
public Long lastLong; @Subscribe
public void listenInteger(Integer event) {
lastInteger = event;
System.out.println("event Integer:"+lastInteger);
} @Subscribe
public void listenLong(Long event) {
lastLong = event;
System.out.println("event Long:"+lastLong);
} public Integer getLastInteger() {
return lastInteger;
} public Long getLastLong() {
return lastLong;
}
}

  测试类:

public class TestMultipleEvents {
@Test
public void testMultipleEvents() throws Exception { EventBus eventBus = new EventBus("test");
MultipleListener multiListener = new MultipleListener(); eventBus.register(multiListener); eventBus.post(new Integer(100));
eventBus.post(new Integer(200));
eventBus.post(new Integer(300));
eventBus.post(new Long(800));
eventBus.post(new Long(800990));
eventBus.post(new Long(800882934)); System.out.println("LastInteger:"+multiListener.getLastInteger());
System.out.println("LastLong:"+multiListener.getLastLong());
}
} //输出信息
event Integer:100
event Integer:200
event Integer:300
event Long:800
event Long:800990
event Long:800882934
LastInteger:300
LastLong:800882934

  Dead Event:

  如果EventBus发送的消息都不是订阅者关心的称之为Dead Event。实例如下:

public class DeadEventListener {
boolean notDelivered = false; @Subscribe
public void listen(DeadEvent event) { notDelivered = true;
} public boolean isNotDelivered() {
return notDelivered;
}
}

  测试类:

public class TestDeadEventListeners {
@Test
public void testDeadEventListeners() throws Exception { EventBus eventBus = new EventBus("test");
DeadEventListener deadEventListener = new DeadEventListener();
eventBus.register(deadEventListener); eventBus.post(new TestEvent(200));
eventBus.post(new TestEvent(300)); System.out.println("deadEvent:"+deadEventListener.isNotDelivered()); }
} //输出信息
event message:200
event message:300
deadEvent:true

  说明:如果没有消息订阅者监听消息, EventBus将发送DeadEvent消息,这时我们可以通过log的方式来记录这种状态。

  Event的继承:

  如果Listener A监听Event A, 而Event A有一个子类Event B, 此时Listener A将同时接收Event A和B消息,实例如下:

  Listener 类:

public class NumberListener {  

    private Number lastMessage;  

    @Subscribe
public void listen(Number integer) {
lastMessage = integer;
System.out.println("Message:"+lastMessage);
} public Number getLastMessage() {
return lastMessage;
}
} public class IntegerListener { private Integer lastMessage; @Subscribe
public void listen(Integer integer) {
lastMessage = integer;
System.out.println("Message:"+lastMessage);
} public Integer getLastMessage() {
return lastMessage;
}
}

  测试类:

public class TestEventsFromSubclass {
@Test
public void testEventsFromSubclass() throws Exception { EventBus eventBus = new EventBus("test");
IntegerListener integerListener = new IntegerListener();
NumberListener numberListener = new NumberListener();
eventBus.register(integerListener);
eventBus.register(numberListener); eventBus.post(new Integer(100)); System.out.println("integerListener message:"+integerListener.getLastMessage());
System.out.println("numberListener message:"+numberListener.getLastMessage()); eventBus.post(new Long(200L)); System.out.println("integerListener message:"+integerListener.getLastMessage());
System.out.println("numberListener message:"+numberListener.getLastMessage());
}
} //输出类
Message:100
Message:100
integerListener message:100
numberListener message:100
Message:200
integerListener message:100
numberListener message:200

  说明:在这个方法中,我们看到第一个事件(新的整数(100))是收到两个听众,但第二个(新长(200 l))只能到达NumberListener作为整数一不是创建这种类型的事件。可以使用此功能来创建更通用的监听器监听一个广泛的事件和更详细的具体的特殊的事件。

  一个综合实例:

public class UserThread extends Thread {
private Socket connection;
private EventBus channel;
private BufferedReader in;
private PrintWriter out; public UserThread(Socket connection, EventBus channel) {
this.connection = connection;
this.channel = channel;
try {
in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
out = new PrintWriter(connection.getOutputStream(), true);
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
} @Subscribe
public void recieveMessage(String message) {
if (out != null) {
out.println(message);
System.out.println("recieveMessage:"+message);
}
} @Override
public void run() {
try {
String input;
while ((input = in.readLine()) != null) {
channel.post(input);
}
} catch (IOException e) {
e.printStackTrace();
} //reached eof
channel.unregister(this);
try {
connection.close();
} catch (IOException e) {
e.printStackTrace();
}
in = null;
out = null;
}
}
mport java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket; import com.google.common.eventbus.EventBus; public class EventBusChat {
public static void main(String[] args) {
EventBus channel = new EventBus();
ServerSocket socket;
try {
socket = new ServerSocket(4444);
while (true) {
Socket connection = socket.accept();
UserThread newUser = new UserThread(connection, channel);
channel.register(newUser);
newUser.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

  说明:用telnet命令登录:telnet 127.0.0.1 4444 ,如果你连接多个实例你会看到任何消息发送被传送到其他实例。

 

Guava学习笔记:EventBus的更多相关文章

  1. Guava学习笔记目录

    Guava 是一个 Google 的基于java1.6的类库集合的扩展项目,包括 collections, caching, primitives support, concurrency libra ...

  2. guava 学习笔记 使用瓜娃(guava)的选择和预判断使代码变得简洁

    guava 学习笔记 使用瓜娃(guava)的选择和预判断使代码变得简洁 1,本文翻译自 http://eclipsesource.com/blogs/2012/06/06/cleaner-code- ...

  3. guava 学习笔记(二) 瓜娃(guava)的API快速熟悉使用

    guava 学习笔记(二) 瓜娃(guava)的API快速熟悉使用 1,大纲 让我们来熟悉瓜娃,并体验下它的一些API,分成如下几个部分: Introduction Guava Collection ...

  4. Guava学习笔记:EventBus(转)

    EventBus是Guava的事件处理机制,是设计模式中的观察者模式(生产/消费者编程模型)的优雅实现.对于事件监听和发布订阅模式,EventBus是一个非常优雅和简单解决方案,我们不用创建复杂的类和 ...

  5. Guava学习笔记(一)概览

    Guava是谷歌开源的一套Java开发类库,以简洁的编程风格著称,提供了很多实用的工具类, 在之前的工作中应用过Collections API和Guava提供的Cache,不过对Guava没有一个系统 ...

  6. Guava学习笔记:Google Guava 类库简介

    http://www.cnblogs.com/peida/tag/Guava/ Guava 是一个 Google 的基于java1.6的类库集合的扩展项目,包括 collections, cachin ...

  7. Guava学习笔记(1):Optional优雅的使用null

    转自:http://www.cnblogs.com/peida/archive/2013/06/14/Guava_Optional.html 参考:[Google Guava] 1.1-使用和避免nu ...

  8. Guava学习笔记:Optional优雅的使用null

    在我们学习和使用Guava的Optional之前,我们需要来了解一下Java中null.因为,只有我们深入的了解了null的相关知识,我们才能更加深入体会领悟到Guava的Optional设计和使用上 ...

  9. Guava学习之EventBus

    一.EventBus的使用案例 EventBus是Guava的事件处理机制,是设计模式中的观察者模式(生产/消费者编程模型)的优雅实现.对于事件监听和发布订阅模式,EventBus是一个非常优雅和简单 ...

随机推荐

  1. java学习笔记--this 关键字的理解

    彻底理解this 关键字的含义 this关键字再java里面是一个我认为非常不好理解的概念,:)也许是太笨的原因 this 关键字的含义:可为以调用了其方法的那个对象生成相应的句柄. 怎么理解这段话呢 ...

  2. Masonry -- 使用纯代码进行iOS应用的autolayout自适应布局

    简介 简化iOS应用使用纯代码机型自适应布局的工作,使用一种简洁高效的语法替代NSLayoutConstraints. 项目主页: Masonry 最新示例: 点击下载 项目简议: 如果再看到关于纯代 ...

  3. js 四舍五入函数 toFixed(),小数位数精度

    js的加减乘除有时得到的结果的小数的位数非常大,这种结果非常难以读取,例如某两个数相乘得到的结果是:1.3921000000000001 这种结果小数的位数有点多,一般需要的结果是四舍无入的 1.39 ...

  4. 每天一个linux命令(31): /etc/group文件详解

    Linux /etc/group文件与/etc/passwd和/etc/shadow文件都是有关于系统管理员对用户和用户组管理时相关的文件.linux /etc/group文件是有关于系统管理员对用户 ...

  5. cordova platform add specified version

    cordova platform add specified version 命令格式 cordova platform add android@4.0 可用的版本 Valid install tar ...

  6. 【WP8.1开发】基于应用的联系人存储

    上一篇文章所吹的牛是访问系统(手机)上的联系人,当然那只是读不能改,这是自然的,要是让你能随便修改用户的联系人信息的话,那后果很严重,有些恶意开发者就有可能把”你的户口改成猪“. 但是,API也允许应 ...

  7. Geometry Curve of OpenCascade BRep

    Geometry Curve of OpenCascade BRep eryar@163.com 摘要Abstract:几何曲线是参数表示的曲线 ,在边界表示中其数据存在于BRep_TEdge中,BR ...

  8. CSS文本方向

    前面的话 一般地,正常网页文本方向都是从上到下,从左到右.实际上,有多种设置文本方向的属性,前面已经详细介绍过text-align,HTML全局属性中有一个"dir"属性就是专门用 ...

  9. 关于AJAX跨域调用ASP.NET MVC或者WebAPI服务的问题及解决方案

      作者:陈希章 时间:2014-7-3 问题描述 当跨域(cross domain)调用ASP.NET MVC或者ASP.NET Web API编写的服务时,会发生无法访问的情况. 重现方式 使用模 ...

  10. Spark入门实战系列--5.Hive(上)--Hive介绍及部署

    [注]该系列文章以及使用到安装包/测试数据 可以在<倾情大奉送--Spark入门实战系列>获取 .Hive介绍 1.1 Hive介绍 月开源的一个数据仓库框架,提供了类似于SQL语法的HQ ...