博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java-类库-Guava-EventBus
阅读量:6548 次
发布时间:2019-06-24

本文共 7498 字,大约阅读时间需要 24 分钟。

  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:200Message:200event message:300Message:300event message:400Message:400LastMessage: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:100event Integer:200event Integer:300event Long:800event Long:800990event Long:800882934LastInteger:300LastLong: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 DeadEventListener {
boolean notDelivered = false; @Subscribe public void listen(DeadEvent event) { notDelivered = true; } public boolean isNotDelivered() { return notDelivered; } }

说明:如果没有消息订阅者监听消息, 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:100Message:100integerListener message:100numberListener message:100Message:200integerListener message:100numberListener 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 ,如果你连接多个实例你会看到任何消息发送被传送到其他实例

转载地址:http://mxgdo.baihongyu.com/

你可能感兴趣的文章
[直播一揽子]编码构思和套路
查看>>
[直播一揽子]x264参数的解释
查看>>
iOS学习之Objective-C 2.0 运行时系统编程
查看>>
Exchange2007-Exchange2010升级-06 数据库高可用组的创建
查看>>
phpHiveAdmin是如何通过Hive/Hadoop工作的
查看>>
双向链表内结点的删除(4)
查看>>
项目总结
查看>>
JSON字符串转成对象
查看>>
SaltStack 中ZMQ升级
查看>>
exchange 2013 提示“HTTP 500内部服务器错误”
查看>>
Linux运维学习笔记之一:运维的原则和学习方法
查看>>
怎样使用原型设计中的组件样式功能
查看>>
python threading
查看>>
谷安天下2013年6月CISA考前辅导 第一季
查看>>
ARM程序规范
查看>>
Qt下的OpenGL 编程(8)文字、FPS、动画
查看>>
记一次mapreduce读取不到输入文件的问题
查看>>
我的友情链接
查看>>
在普通台式机上搭建服务器虚拟化架构Esxi平台
查看>>
电话线路 30B+D 名词解释
查看>>