Guava学习笔记:EventBus

本文深入讲解了Guava的EventBus机制,这是一种优雅实现的观察者模式。通过示例介绍了EventBus的基本用法、多监听器的使用、DeadEvent处理、事件继承等特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[url]http://my.oschina.net/u/2311010/blog/515188[/url]
摘要 EventBus是Guava的事件处理机制,是设计模式中的观察者模式(生产/消费者编程模型)的优雅实现。对于事件监听和发布订阅模式,EventBus是一个非常优雅和简单解决方案,我们不用创建复杂的类和接口层次结构。   Observer模式是比较常用的设计模式之一,虽然有时候在具体代码里,它不一定叫这个名字,比如改头换面叫个Listener,但模式就是这个模式。手工实现一个Observer也不是多复杂的一件事,只是因为这个设计模式实在太常用了,Java就把它放到了JDK里面:Observable和Observer,从JDK 1.0里,它们就一直在那里。从某种程度上说,它简化了Obser...


[b]EventBus基本用法:[/b]

使用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());

}
}

//输出信息
[color=gray]event message:200
Message:200
event message:300
Message:300
event message:400
Message:400
LastMessage:400[/color]


[b]MultiListener的使用:[/b]

只需要在要订阅消息的方法上加上@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());
}
}


//输出信息
[color=gray]event Integer:100
event Integer:200
event Integer:300
event Long:800
event Long:800990
event Long:800882934
LastInteger:300
LastLong:800882934[/color]


[b]Dead Event:[/b]

如果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());

}
}


//输出信息
[color=gray]event message:200
event message:300
deadEvent:true[/color]

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

[b]Event的继承:[/b]

如果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());
}
}


//输出类
[color=gray]Message:100
Message:100
integerListener message:100
numberListener message:100
Message:200
integerListener message:100
numberListener message:200[/color]

说明:在这个方法中,我们看到第一个事件(新的整数(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;
}
}

import 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 ,如果你连接多个实例你会看到任何消息发送被传送到其他实例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值