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注解即可。代码如下:

  消息封装类:

  1. public class TestEvent {
  2. private final int message;
  3. public TestEvent(int message) {
  4. this.message = message;
  5. System.out.println("event message:"+message);
  6. }
  7. public int getMessage() {
  8. return message;
  9. }
  10. }

  消息接受类:

  1. public class EventListener {
  2. public int lastMessage = 0;
  3.  
  4. @Subscribe
  5. public void listen(TestEvent event) {
  6. lastMessage = event.getMessage();
  7. System.out.println("Message:"+lastMessage);
  8. }
  9.  
  10. public int getLastMessage() {
  11. return lastMessage;
  12. }
  13. }

  测试类及输出结果:

  1. public class TestEventBus {
  2. @Test
  3. public void testReceiveEvent() throws Exception {
  4.  
  5. EventBus eventBus = new EventBus("test");
  6. EventListener listener = new EventListener();
  7.  
  8. eventBus.register(listener);
  9.  
  10. eventBus.post(new TestEvent(200));
  11. eventBus.post(new TestEvent(300));
  12. eventBus.post(new TestEvent(400));
  13.  
  14. System.out.println("LastMessage:"+listener.getLastMessage());
  15. ;
  16. }
  17. }
  18.  
  19. //输出信息
  20. event message:200
  21. Message:200
  22. event message:300
  23. Message:300
  24. event message:400
  25. Message:400
  26. LastMessage:400

  MultiListener的使用:

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

  1. public class MultipleListener {
  2. public Integer lastInteger;
  3. public Long lastLong;
  4.  
  5. @Subscribe
  6. public void listenInteger(Integer event) {
  7. lastInteger = event;
  8. System.out.println("event Integer:"+lastInteger);
  9. }
  10.  
  11. @Subscribe
  12. public void listenLong(Long event) {
  13. lastLong = event;
  14. System.out.println("event Long:"+lastLong);
  15. }
  16.  
  17. public Integer getLastInteger() {
  18. return lastInteger;
  19. }
  20.  
  21. public Long getLastLong() {
  22. return lastLong;
  23. }
  24. }

  测试类:

  1. public class TestMultipleEvents {
  2. @Test
  3. public void testMultipleEvents() throws Exception {
  4.  
  5. EventBus eventBus = new EventBus("test");
  6. MultipleListener multiListener = new MultipleListener();
  7.  
  8. eventBus.register(multiListener);
  9.  
  10. eventBus.post(new Integer(100));
  11. eventBus.post(new Integer(200));
  12. eventBus.post(new Integer(300));
  13. eventBus.post(new Long(800));
  14. eventBus.post(new Long(800990));
  15. eventBus.post(new Long(800882934));
  16.  
  17. System.out.println("LastInteger:"+multiListener.getLastInteger());
  18. System.out.println("LastLong:"+multiListener.getLastLong());
  19. }
  20. }
  21.  
  22. //输出信息
  23. event Integer:100
  24. event Integer:200
  25. event Integer:300
  26. event Long:800
  27. event Long:800990
  28. event Long:800882934
  29. LastInteger:300
  30. LastLong:800882934

  Dead Event:

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

  1. public class DeadEventListener {
  2. boolean notDelivered = false;
  3.  
  4. @Subscribe
  5. public void listen(DeadEvent event) {
  6.  
  7. notDelivered = true;
  8. }
  9.  
  10. public boolean isNotDelivered() {
  11. return notDelivered;
  12. }
  13. }

  测试类:

  1. public class TestDeadEventListeners {
  2. @Test
  3. public void testDeadEventListeners() throws Exception {
  4.  
  5. EventBus eventBus = new EventBus("test");
  6. DeadEventListener deadEventListener = new DeadEventListener();
  7. eventBus.register(deadEventListener);
  8.  
  9. eventBus.post(new TestEvent(200));
  10. eventBus.post(new TestEvent(300));
  11.  
  12. System.out.println("deadEvent:"+deadEventListener.isNotDelivered());
  13.  
  14. }
  15. }
  16.  
  17. //输出信息
  18. event message:200
  19. event message:300
  20. deadEvent:true

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

  Event的继承:

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

  Listener 类:

  1. public class NumberListener {
  2.  
  3. private Number lastMessage;
  4.  
  5. @Subscribe
  6. public void listen(Number integer) {
  7. lastMessage = integer;
  8. System.out.println("Message:"+lastMessage);
  9. }
  10.  
  11. public Number getLastMessage() {
  12. return lastMessage;
  13. }
  14. }
  15.  
  16. public class IntegerListener {
  17.  
  18. private Integer lastMessage;
  19.  
  20. @Subscribe
  21. public void listen(Integer integer) {
  22. lastMessage = integer;
  23. System.out.println("Message:"+lastMessage);
  24. }
  25.  
  26. public Integer getLastMessage() {
  27. return lastMessage;
  28. }
  29. }

  测试类:

  1. public class TestEventsFromSubclass {
  2. @Test
  3. public void testEventsFromSubclass() throws Exception {
  4.  
  5. EventBus eventBus = new EventBus("test");
  6. IntegerListener integerListener = new IntegerListener();
  7. NumberListener numberListener = new NumberListener();
  8. eventBus.register(integerListener);
  9. eventBus.register(numberListener);
  10.  
  11. eventBus.post(new Integer(100));
  12.  
  13. System.out.println("integerListener message:"+integerListener.getLastMessage());
  14. System.out.println("numberListener message:"+numberListener.getLastMessage());
  15.  
  16. eventBus.post(new Long(200L));
  17.  
  18. System.out.println("integerListener message:"+integerListener.getLastMessage());
  19. System.out.println("numberListener message:"+numberListener.getLastMessage());
  20. }
  21. }
  22.  
  23. //输出类
  24. Message:100
  25. Message:100
  26. integerListener message:100
  27. numberListener message:100
  28. Message:200
  29. integerListener message:100
  30. numberListener message:200

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

  一个综合实例:

  1. public class UserThread extends Thread {
  2. private Socket connection;
  3. private EventBus channel;
  4. private BufferedReader in;
  5. private PrintWriter out;
  6.  
  7. public UserThread(Socket connection, EventBus channel) {
  8. this.connection = connection;
  9. this.channel = channel;
  10. try {
  11. in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
  12. out = new PrintWriter(connection.getOutputStream(), true);
  13. } catch (IOException e) {
  14. e.printStackTrace();
  15. System.exit(1);
  16. }
  17. }
  18.  
  19. @Subscribe
  20. public void recieveMessage(String message) {
  21. if (out != null) {
  22. out.println(message);
  23. System.out.println("recieveMessage:"+message);
  24. }
  25. }
  26.  
  27. @Override
  28. public void run() {
  29. try {
  30. String input;
  31. while ((input = in.readLine()) != null) {
  32. channel.post(input);
  33. }
  34. } catch (IOException e) {
  35. e.printStackTrace();
  36. }
  37.  
  38. //reached eof
  39. channel.unregister(this);
  40. try {
  41. connection.close();
  42. } catch (IOException e) {
  43. e.printStackTrace();
  44. }
  45. in = null;
  46. out = null;
  47. }
  48. }
  1. mport java.io.IOException;
  2. import java.net.ServerSocket;
  3. import java.net.Socket;
  4.  
  5. import com.google.common.eventbus.EventBus;
  6.  
  7. public class EventBusChat {
  8. public static void main(String[] args) {
  9. EventBus channel = new EventBus();
  10. ServerSocket socket;
  11. try {
  12. socket = new ServerSocket(4444);
  13. while (true) {
  14. Socket connection = socket.accept();
  15. UserThread newUser = new UserThread(connection, channel);
  16. channel.register(newUser);
  17. newUser.start();
  18. }
  19. } catch (IOException e) {
  20. e.printStackTrace();
  21. }
  22. }
  23. }

  说明:用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. 移动端IM开发需要面对的技术问题

    1.前言 这两年多一直从事网易云信 iOS 端 IM SDK的开发,期间不断有兄弟部门的同事和合作伙伴过来问各种技术细节,干脆统一介绍下一个IM APP的方方面面,包括技术选型(包括通讯方式,网络连接 ...

  2. JS原生第二篇 (帅哥)

    1.1 Javascript 作用  1.  网页特效 2. 用户交互 3. 表单验证 Js  就是可以用来控制   结构  和 样式 . 1.2  体验js   认识常用的三个输出语句.  都属于 ...

  3. [转载]基于TFS实践敏捷-实现用户场景

    您是新用户的 Visual Studio 应用程序生命周期管理 (ALM) 和 Team Foundation Server (TFS) 吗? 您想知道如何您和您的团队可以获得最大受益的这些工具来生成 ...

  4. NodeJS实战:Express+Mongoose+ejs

    元宵还没到,先向所有朋友拜一个晚年~~~ 文章目录: 1.组件版本号 -- --node -- --express -- --Mongoose 2.初始化项目 firstblood -- --用 ex ...

  5. 如何给wordpress首页自动显示文章内容的第一个图片

    敏捷个人手机应用中使用到的数据来源于wordpress中,因为自己写的页面,所以可以自己写代码获取文章内容的第一个图片作为文章缩略图来显示,这样用户看到首页时图文并茂,感觉会好一些. 现在后台简单的使 ...

  6. Android自动化测试之Monkeyrunner学习笔记(一)

    Android自动化测试之Monkeyrunner学习笔记(一) 因项目需要,开始研究Android自动化测试方法,对其中的一些工具.方法和框架做了一些简单的整理,其中包括Monkey.Monkeyr ...

  7. Theano入门神经网络(二) 实现一个XOR门

    与非门的图片如下 示意图 详细解释: 1 定义变量的代码,包括了输入.权值.输出等.其中激活函数采用的是sigmod函数 # -*- coding: utf-8 -*- __author__ = 'A ...

  8. 【转载】ASP.NET MVC Web API 的路由选择

    此文章描述了ASP.NET Web API如何将Http请求路由到controller. 路由表 在ASP.NET Web API中,controller是用来处理HTTP请求的一个类.这个类中用于处 ...

  9. 反射(Reflection)的SetValue遇上DBNULL转换为string

    有网友回馈说提供的代码有bug.你可以从这个链接下载得到:http://www.cnblogs.com/insus/p/3384472.html 其中有一个Utility,它是把DataTable转换 ...

  10. HoverTree开源项目已经实现管理员登录

    ASP.NET开源项目HoverTree已经实现了管理员登录功能,最新代码请到以下网址查看.http://hovertree.com/down/ 点击Clone右边的Download就可以下载最新开发 ...