1. 背景
最近新换了工作,刚来比较轻松,所以想自己写几个小工具提升下自己的效率。在开发过程中发现组件的一些通讯问题,如果采用异步的方式,效率能得到很大提升,所以决定使用到EventBus(消息总线)技术,达到异步事件处理的目的。
2. EventBus
EventBus是事件总线,事件发送者会将消息发送到总线上,事件订阅者向事件总线订阅和接受事件并进行处理。订阅者不只是可以订阅消息,它同样也可以是消息发送者。
3. 实现方式
3.1 Guava EventBus
Guava EventBus 提供了一个发布-订阅事件机制,该机制允许对象通过观察者模式相互通信,Guava工具中提供的EventBus提供同步和异步两种方式。下面分别看下如何实现。
3.1.1 同步总线(以下代码为代码片段,请酌情使用)
// 创建一个EventBus对象 EventBus logEventBus = new EventBus("log"); EventBus commandEventBus = new EventBus("command"); // 定义两消息类型 @Data public class EventMessage { /** * 消息ID */ protected String messageId = UUID.randomUUID().toString(); /** * 消息生成时间 */ protected LocalDateTime last = LocalDateTime.now(); } @Data @ToString public class CommandMessage extends EventMessage { /** * 作用平台 */ private PlatformEnum platform; /** * 命令类型 */ private int commandType; /** * 命令 */ private String command; } @Data @ToString public class LogMessage extends EventMessage { /** * 日志内容 */ private String content; } // 定义一个listener类 public class EventListener { @Subscribe public void listenLogEvent(LogMessage logMessage) { System.out.println("EventListener#listenLogEvent ->" + logMessage); } @Subscribe public void listenCommandEvent(CommandMessage commandMessage) { System.out.println("EventListener#listenCommandEvent ->" + commandMessage); } } // 绑定总线并发送消息 LogMessage logMessage = new LogMessage(); logMessage.setContent("我是一个日志消息"); logEventBus.post(logMessage); CommandMessage commandMessage = new CommandMessage(); commandMessage.setCommand("ipconfig"); commandMessage.setCommandType(1); commandMessage.setPlatform(PlatformEnum.WINDOWS); commandEventBus.post(commandMessage); // 打印结果 EventListener#listenLogEvent ->LogMessage(content=我是一个日志消息) EventListener#listenCommandEvent ->CommandMessage(platform=WINDOWS, commandType=1, command=ipconfig)
3.1.2 异步总线(以下代码为代码片段,请酌情使用)
// 创建一个EventBus对象 AsyncEventBus logEventBus = new AsyncEventBus("log"); AsyncEventBus commandEventBus = new AsyncEventBus("command"); // 其余代码同同步代码片段,省略...
3.1.3 异常处理
// 可在创建EventBus时创建一个捕获异常的handler EventBus eventBus = new EventBus((exception, context) -> { System.out.println(exception.getCause()); });