Guava学习笔记:EventBus
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的更多相关文章
- Guava学习笔记目录
Guava 是一个 Google 的基于java1.6的类库集合的扩展项目,包括 collections, caching, primitives support, concurrency libra ...
- guava 学习笔记 使用瓜娃(guava)的选择和预判断使代码变得简洁
guava 学习笔记 使用瓜娃(guava)的选择和预判断使代码变得简洁 1,本文翻译自 http://eclipsesource.com/blogs/2012/06/06/cleaner-code- ...
- guava 学习笔记(二) 瓜娃(guava)的API快速熟悉使用
guava 学习笔记(二) 瓜娃(guava)的API快速熟悉使用 1,大纲 让我们来熟悉瓜娃,并体验下它的一些API,分成如下几个部分: Introduction Guava Collection ...
- Guava学习笔记:EventBus(转)
EventBus是Guava的事件处理机制,是设计模式中的观察者模式(生产/消费者编程模型)的优雅实现.对于事件监听和发布订阅模式,EventBus是一个非常优雅和简单解决方案,我们不用创建复杂的类和 ...
- Guava学习笔记(一)概览
Guava是谷歌开源的一套Java开发类库,以简洁的编程风格著称,提供了很多实用的工具类, 在之前的工作中应用过Collections API和Guava提供的Cache,不过对Guava没有一个系统 ...
- Guava学习笔记:Google Guava 类库简介
http://www.cnblogs.com/peida/tag/Guava/ Guava 是一个 Google 的基于java1.6的类库集合的扩展项目,包括 collections, cachin ...
- Guava学习笔记(1):Optional优雅的使用null
转自:http://www.cnblogs.com/peida/archive/2013/06/14/Guava_Optional.html 参考:[Google Guava] 1.1-使用和避免nu ...
- Guava学习笔记:Optional优雅的使用null
在我们学习和使用Guava的Optional之前,我们需要来了解一下Java中null.因为,只有我们深入的了解了null的相关知识,我们才能更加深入体会领悟到Guava的Optional设计和使用上 ...
- Guava学习之EventBus
一.EventBus的使用案例 EventBus是Guava的事件处理机制,是设计模式中的观察者模式(生产/消费者编程模型)的优雅实现.对于事件监听和发布订阅模式,EventBus是一个非常优雅和简单 ...
随机推荐
- SqlServer 错误1053:服务并未及时响应启动或控制请求
sqlserver 的登录用户修改成域账户后,启动不了 解决方法: 计算器管理选择管理员组 将域账户加入到管理员组即可
- Hadoop学习笔记【分布式文件系统学习笔记】
分布式文件系统介绍 分布式文件系统:Hadoop Distributed File System,简称HDFS. 一.HDFS简介 Hadoop分布式文件系统(HDFS)被设计成适合运行在通用硬件(c ...
- 常用Math 方法
/** * * @authors Your Name (you@example.org) * @date 2016-11-18 11:26:44 * @version $Id$ */ Math.pow ...
- vue-cli创建项目
- 关于json序列化和反序列的问题,没事写个案例,希望能帮到那些需要帮忙的朋友!
现在关于json的读写问题,有许许多多的解决方法,因人而异,根据实际问题去选择自己想要的最容易方法.我觉得自带的Newtonsoft.Json是个不错的选择,随便写两个例子吧! 一:关于简单的json ...
- javaweb+SSH实现简单的权限管理系统
权限管理,平时里很多地方我们都可以看到,比如聊QQ时群里的群主.管理员以及成员之间的功能是不一样的--大家一定会遇到的一个问题,所以整理 一下自己写权限系统的一些经验给大家,只起参考作用,也望大家笑纳 ...
- 利用SSIS的ForcedExecutionResult 属性 和CheckPoint调试Package
1,ForcedExecutionResult 强制一个package或task执行的结果,共有四种值 None,Success,Failure,Completion,默认值是None,表示不强制返回 ...
- OOCSS入门学习
对于面向对象大家肯定都有多多少少的了解,这里所说的OOCSS就是说面向对象的CSS,得说明的是OOCSS并不是一门新语言也不是什么库,而是一种概念和javascript面向对象一样. 可能你这样写过C ...
- knockoutjs中使用mapping插件绑定数据列表
使用KO绑定数据列表示例: 1.先申请V,T,T2三个辅助方法,方便调试.声明viewModel和加载数据时的映射条件mapping 2.先使用ko.mapping.fromJS()将原来的 ...
- 最近修改的几个小bug
最近修改的几个 bug,问题不大,查找起来却几番周折,汇总起来如下. 1.诡异电话号码 客服邮件反馈,很多用户服务热线变成了“0371-45875487”.看到这问题的第一反映是可能因为程序某个地方有 ...