Guava的EventBus可以简化生产/消费模型。EventBus通过非常简单的方式,实现了观察者模式中的监听注册,事件分发。有了这个玩意,真的可以替换Observer模式了
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。
import com.google.common.eventbus.DeadEvent;
import com.google.common.eventbus.Subscribe;
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; } }
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 ,如果你连接多个实例你会看到任何消息发送被传送到其他实例。
相关推荐
8. **事件监听**:Guava的EventBus可以方便地实现发布/订阅模式,简化事件驱动的编程。 9. **枚举集与常量**:Guava提供了ImmutableEnumSet和ImmutableSet.of()等方法,创建不可变且高效的枚举集合。 `guava-18.0-...
8. **事件监听**:Guava的 EventBus 使得事件驱动编程在Java 5环境下变得可能,它允许组件之间松散耦合,通过发布和订阅事件来进行通信。 9. **运行时类型信息**:Guava提供了TypeToken和Types等工具类,帮助开发者...
在本文中,我们将深入探讨如何在SpringBoot应用中使用EventBus,这是一个基于Guava库的事件总线系统。EventBus的引入使得松耦合的...同时,配合SpringBoot的其他特性,如自动配置和AOP,可以进一步优化事件驱动架构。
这种模式常用于创建事件驱动的系统,使得多个组件能够对特定事件作出响应。在Java中,Guava和Spring框架都提供了实现观察者模式的工具。 Guava的EventBus是观察者模式的一个实例,它简化了事件发布和订阅的过程。...
但是,需要注意的是,当数据库数据发生变化时,需要同步更新缓存,这通常可以通过事件驱动或定时任务实现。 总结,Guava Cache是Java开发中实现本地缓存的一个强大工具,它的灵活性和丰富的特性使得缓存管理变得...
总的来说,虽然标题中的"Node.js-EventBusOttoRxBus事件总线使用"可能与Android开发更相关,但我们可以看到在Android领域,EventBus、Otto和RxBus是实现组件间通信的重要工具。而在Node.js中,我们可以使用内置的...
在Java编程中,事件驱动模型是一种常见的设计模式,它使得组件之间可以相互通信而无需直接耦合。Event Bus(事件总线)是这种模式的一种实现,常用于Android和Java桌面应用。本文将深入探讨Java Event Bus的原理、...
事件驱动架构(Event-Driven Architecture, EDA)是现代软件设计的一种常见模式,特别适用于分布式系统和微服务环境。Avis作为事件总线,扮演着核心角色,它连接发布者(Producer)和订阅者(Consumer),使得不同...
Guava库提供了EventBus,可以帮助实现事件驱动编程;而在多线程处理方面,Java的ExecutorService和CompletableFuture等工具类能帮助我们优雅地管理线程和异步任务。 总的来说,组件模型和双事件处理线程是构建高...
当涉及到更复杂的交互,例如处理JavaScript事件、模拟用户操作或者等待特定元素加载时,Selenium提供了丰富的API供你使用。例如,可以使用`WebDriverWait`来等待某个条件满足,或者使用`ActionChains`来模拟鼠标和...
Otto是由Square公司开发的一个基于Google Guava库的事件总线,用于简化Android应用中的组件间通信。在大型项目中,组件间的通信可能会变得复杂,Otto提供了一种发布/订阅的方式来解决这个问题。 1. **发布(Publish...
事件驱动编程是Java GUI应用的基础,它涉及到ActionListener和MouseListener等接口的实现。例如,当用户点击播放按钮时,对应的ActionListener会被触发,执行播放音乐的方法。同样,当用户在进度条上拖动时,...
这种模式常用于实现事件驱动的系统,使得多个对象能够同步地接收到某个对象状态变化的信息。 在Java中,观察者模式的实现主要依赖于`java.util.Observable`和`java.util.Observer`这两个类。`Observable`类代表被...
为此,可以采用事件驱动的方式,监听数据库的变更事件,触发相应的缓存清理或更新操作。 此外,优化Redis缓存的过期策略也是提高系统稳定性的关键。可以选择设置TTL(Time To Live)让缓存自动过期,或者根据LRU...
- **Netty 框架**:作为Java领域最流行的网络编程库,Netty提供了一套完整的异步事件驱动的网络应用程序框架,可以快速构建高性能的游戏服务器。 3. **并发处理**: - **线程池**:使用ExecutorService创建线程池...
这为异步编程提供了更加灵活的事件驱动模型。 Scala 的 Futures 和 Promises 则是其强大的 Actor 模型和响应式编程的一部分。Scala 的 `Future` 类代表一个异步操作的结果,类似于 Java 和 Guava,但它提供了更多的...
在事件驱动的架构中,事件总线是一种通信机制,允许组件之间通过发布和订阅事件来解耦。传统的事件总线通常采用同步方式,即发布事件后,订阅者会立即处理事件,这可能导致阻塞主线程,影响应用性能。而nox-bus作为...
在Java企业级开发中,Servlet和JSP是两种核心的技术,它们被广泛应用于构建Web...配合适当的jar包,如Servlet和JSP API、JDBC驱动以及辅助库,可以实现与数据库交互、用户界面动态生成等功能,满足企业级应用的需求。
常见的有定时更新、事件驱动更新、版本号校验等。 - **缓存过期策略**:设定合理的过期时间,避免长时间未更新的缓存导致数据陈旧。 - **并发控制**:在多线程环境下,如何保证缓存操作的线程安全,防止数据一致性...
WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...