Google Guava EventBus用于事件编程

在任何软件应用程序中都是如此,有些对象需要共享信息才能完成工作。 在Java应用程序中,实现信息共享的一种方法是拥有事件侦听器,其唯一目的是在发生所需事件时采取某些措施。 在大多数情况下,此过程有效,并且最有经验的Java开发人员习惯于编写实现某些事件侦听器接口的必需的匿名内部类。 这篇文章是关于使用Guava的EventBus处理Java事件的另一种方法。 EventBus允许对象订阅发布事件,而无需彼此明确了解。 EventBus并不旨在成为通用的发布/订阅系统,也不支持进程间通信。

EventBus类别

EventBus非常灵活,可以用作单例,或者应用程序可以具有多个实例以适应在不同上下文中传输事件。 EventBus将按顺序分派所有事件,因此,保持事件处理方法的轻量化很重要。 如果需要在事件处理程序中进行更重的处理,则可以使用EventBus的另一种形式,即AsyncEventBus。 AsyncEventBus在功能上是相同的,但是采用ExecutorService作为构造函数参数来允许事件的异步调度。

订阅活动

对象通过以下步骤预订事件:

  1. 定义一个采用所需事件类型的单个参数的公共方法,并在该方法上放置@Subscribe批注。
  2. 通过将对象的实例传递给EventBus.register方法来向EventBus注册。

这是一个简短的示例,为清楚起见省略了详细信息:

public class PurchaseSubscriber {@Subscribepublic void handlePurchaseEvent(PurchaseEvent event) {.....}.....EventBus eventBus = new EventBus();PurchaseSubscriber purchaseSubscriber = new PurchaseSubscriber();eventBus.register(purchaseSubscriber);

还有一个可以与@Subscribe结合使用的注释,即@AllowConcurrentEvents。 @AllowConcurrentEvents将处理程序方法标记为线程安全的,因此EventBus(很可能是AsyncEventBus)可以潜在地从同时线程调用事件处理程序。 我在单元测试中发现的一件有趣的事情是,如果处理程序方法没有@AllowConcurrentEvents批注,则即使使用AsyncEventBus,它也会按顺序调用事件的处理程序。 重要的是要注意,@ AllowConcurrentEvents不会将方法标记为事件处理程序,@ Subscribe批注仍需要存在。 最后,事件处理方法必须具有一个且只有一个参数,否则当您在EventBus中注册对象时,将抛出IllegalArgumentException。

发布事件

同样,使用EventBus发布事件也很简单。 在您要发送事件通知的代码部分中,调用EventBus.post,将为该事件对象注册的所有订阅者进行通知。

public void handleTransaction(){purchaseService.purchase(item,amount);eventBus.post(new CashPurchaseEvent(item,amount));....}

尽管这很明显,但是订阅类和发布类共享同一EventBus实例很重要,并且使用Guice或Spring帮助管理依赖项是有意义的。

有关事件处理程序的更多信息

EventBus的一项非常强大的功能是,您可以根据需要使处理程序正常运行或细化。 EventBus将为已发布事件对象的所有子类型和已实现的接口调用注册的订户。 例如,要处理所有事件,可以创建一个带有Object类型参数的事件处理程序。 要仅处理单个事件,请创建一个特定于类型的处理程序。 为了帮助说明,请考虑以下简单事件层次结构:

public abstract class PurchaseEvent {String item;public PurchaseEvent(String item){this.item = item;}
}public class CashPurchaseEvent extends PurchaseEvent {int amount;public CashPurchaseEvent(String item, int amount){super(item);this.amount = amount;}
}public class CreditPurchaseEvent extends PurchaseEvent {int amount;String cardNumber;public CreditPurchaseEvent(String item,int amount, String cardNumber){super(item);this.amount = amount;this.cardNumber = cardNumber;}
}

以下是相应的事件处理类:

//Would only be notified of Cash purchase eventspublic class CashPurchaseSubscriber {@Subscribepublic void handleCashPurchase(CashPurchaseEvent event){... }}//Would only be notified of credit purchasespublic class CreditPurchaseSubscriber {@Subscribepublic void handleCreditPurchase(CreditPurchaseEvent event) {....}
}
//Notified of any purchase eventpublic class PurchaseSubscriber {@Subscribepublic void handlePurchaseEvent(PurchaseEvent event) {.....}
}

如果需要捕获各种各样的事件类型,则替代方法是在一个类中具有多个事件处理方法。 拥有多个处理程序可能是一个更好的解决方案,因为您不必对事件对象参数进行任何“ instanceof”检查。 这是我的单元测试中的一个简单示例:

public class MultiHandlerSubscriber {List<CashPurchaseEvent> cashEvents = new ArrayList<ashPurchaseEvent>();List<CreditPurchaseEvent> creditEvents = new ArrayList<CreditPurchaseEvent>();List<SimpleEvent> simpleEvents = new ArrayList<SimpleEvent>();public MultiHandlerSubscriber(EventBus eventBus){eventBus.register(this);}@Subscribepublic void handleCashEvents(CashPurchaseEvent event){cashEvents.add(event);}@Subscribepublic void handleCreditEvents(CreditPurchaseEvent event){creditEvents.add(event);}@Subscribepublic void handleSimpleEvents(SimpleEvent event){simpleEvents.add(event);}
....


测试中

由于事件处理程序只是普通方法,因此可以通过在测试用例中实例化一个EventBus或通过传递适当的事件对象来模拟EventBus来轻松对其进行测试。 当使用EventBus时,我发现很容易:

  • 忘记在EventBus中注册订阅对象
  • 忽略添加@Subscribe批注。

如果似乎未调用事件处理程序,请首先检查这两个错误。
一种有用的调试技术是订阅DeadEvent类。 EventBus将在DeadEvent实例中包装任何没有处理程序的已发布事件。 DeadEvent提供了getEvent方法,该方法返回原始事件对象。

结论

Guava EventBus类为标准Java事件处理机制提供了一种有吸引力且有用的替代方法。 希望读者会发现EventBus像我一样有用。 一如既往地欢迎提出意见和建议。

资源资源

  • EventBus API
  • 番石榴API
  • 样例代码
  • 活动合作


参考:来自我们的JCG合作伙伴 Bill Bejeck的Google Guava EventBus进行事件编程,来自Random Thoughts On Coding博客。

翻译自: https://www.javacodegeeks.com/2012/11/google-guava-eventbus-for-event-programming.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/370444.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

system类

package system.cn; /** system类的方法 都是静态方法&#xff0c;可以直接用类名直接调用* 常用的方法&#xff1a;* static long currentTimeMillis() 返回以毫秒为单位的当前时间。 static void exit(int status) 终止当前正在运行的 Java 虚拟机。 static void gc…

c await和java_blog/java/test/awaitility.zh.md at master · c-rainstorm/blog · GitHub

javaAtomicInteger atomic new AtomicInteger(0);// Do some async stuff that eventually updates the atomic integerawait().untilAtomic(atomic, equalTo(1));等待一个 AtomicBoolean 更简单&#xff1a;javaAtomicBoolean atomic new AtomicBoolean(false);// Do some a…

实现输入框小数多 自动进位展示,编辑时实际值不变

今天遇到个业务需求&#xff0c;要求输入框&#xff0c;输入数字的小数位数可以很多位&#xff0c;但移开后显示&#xff0c;只显示小数点后两位 &#xff08;四舍五入&#xff09;&#xff0c;当要编辑的时候&#xff0c;展现其原来的输入数据。 闲话不多说&#xff0c;当时也…

使用Jasper Reports以Java创建报告

上周&#xff0c;我试图使用Jasper创建报告。 在这篇文章中&#xff0c;我将记录一些资源和链接&#xff0c;以便对任何寻求类似信息的人都有用。 我将介绍Jasper报告&#xff0c;示例和Dynamic Jasper的生命周期。 Jasper Reports是世界上最受欢迎的开源报告引擎。 它完全用…

CentOS7 安装NodeJS

一、切换目录到/usr/local/src 命令行&#xff1a;cd /usr/local/src 二、下载node.js&#xff08;我这里下载的是二进制的源码&#xff09; 命令行&#xff1a; wget https://nodejs.org/dist/v8.9.1/node-v8.9.1-linux-x64.tar.xz 图片&#xff1a; 三、解压压缩包 命令行&am…

CSS3基础2(变形与动画)

<!DOCTYPE html5><html lang"en"><head> <meta charset"UTF-8"> <title>CSS3基础知识&#xff08;动画&#xff09;</title> <style> /*div{*/ /*width: 150px;*/ /*hei…

java对hashmap迭代_Java:通过HashMap迭代,这样更有效率?

第二个选项肯定更有效&#xff0c;因为在第一个选项中只进行一次查找&#xff0c;次数为n次。但是&#xff0c;没有什么比尝试它更好&#xff0c;当你可以。所以这里 –(不完美&#xff0c;但足够好验证假设和我的机器)public static void main(String args[]) {Map map new H…

html-edm(邮件营销)编写规则

最近写了一个edm邮件 以前没有接触过 使用的是很老的html页面编写规则 只能用table标签 在此记录一下edm编写的一些规则 个人参考的是这两个网址&#xff0c;转载一下 http://www.zcool.com.cn/article/ZMTM5MDgw.html https://www.cnblogs.com/lhweb15/p/6404626.html …

ASP.NET Core2.0 环境下MVC模式的支付宝PC网站支付接口-沙箱环境开发测试

1.新建.NET Core web项目 2.Controllers-Models-Views 分三个大部分 3.下载安装最新sdk 官方的SDK以及Demo都还是.NET Framework的&#xff0c;根据官方文档说明新建网站后还是需要引用官方SDK的源码&#xff0c; 在这里直接使用网上一位朋友的用.NET Standard 2.0 进行实现了支…

如何在redhat8里使用gcc命令_如何使用who命令检查用户登录信息

请关注本头条号&#xff0c;每天坚持更新原创干货技术文章。如需学习视频&#xff0c;请在微信搜索公众号“智传网优”直接开始自助视频学习1. 前言本教程主要介绍如何使用who命令检查用户登录信息。如何使用who命令检查用户登录信息Linux中的who命令列出了系统上的所有登录用户…

研究僵局–第4部分:修复代码

在这个简短的博客系列的最后BadTransferOperation中&#xff0c;我一直在讨论分析死锁&#xff0c;我将修复BadTransferOperation代码。 如果您看过本系列的其他博客 &#xff0c;那么您将知道&#xff0c;为了达到这一点&#xff0c;我创建了死锁的演示代码&#xff0c;展示了…

chrome插件2

转自&#xff1a;http://www.codeceo.com/article/15-chrome-extension.html 1. Web Developer 支持Chrome的Web Developer扩展&#xff0c;允许你通过添加一个小工具栏来使用不同的工具。 官方网站&#xff1a;https://chrome.google.com/webstore/detail/web-developer/bfbam…

java月历组件_vue之手把手教你写日历组件

---恢复内容开始---1.日历组件1.分析功能&#xff1a;日历基本功能&#xff0c;点击事件改变日期&#xff0c;样式的改变1.结构分析&#xff1a;html1.分为上下两个部分2.上面分为左按钮&#xff0c;中间内容展示&#xff0c;右按钮下面分为周几展示和日期展示3.基本结构页面ht…

HTML5和css3

超链接 <a target"页面打开位置" href"链接地址">内容</a>target:_blank 重新打开一个页面target:_self 当前页面打开 1.页面地址&#xff1a; 基础功能&#xff0c;用于进入该链接的页面&#xff1b; 2.锚点&#xff1a; 需要给标签名定义id…

python下载显示文件丢失_Microsoft.PythonTools.resources.dll

我该如何安装从金山毒霸下载的DLL文件&#xff1f;一&#xff1a;1、从金山毒霸下载压缩文件。2、将DLL文件解压到电脑上的某个地方。3、把该文件跟要求使用它的程序放在同一路径上。注意32位程序需要使用32位的DLL文件&#xff0c;64位程序需要使用64位的DLL文件。否则会出现0…

maven project module 依赖项目创建 ---转

一、创建Maven Project 1.右击 --> New --> Other&#xff0c;--> Maven --> Maven Project --> Next 2.如下图&#xff0c;选中Create a simple project --> Next 3.输入Group Id, Artifact Id, Version, Packaging选择pom&#xff0c;因为创建的Maven Pr…

java soot_正确执行3个地址代码的SOOT API

我在运行SOOT API时遇到问题 . 我正在使用java -cp soot-2.5.0.jar soot.Main -f jimple test我遇到以下错误&#xff1a;Exception in thread "main" java.lang.RuntimeException: Could not load classfile: java.io.ObjectInputStream atat soot.coffi.Util.resol…

JSF AJAX请求的会话超时处理

JSF AJAX请求的会话超时处理 当我们使用AJAX行为开发JSF应用程序时&#xff0c;在处理Ajax请求超时场景时可能会遇到问题。 例如&#xff0c;如果您使用的是基于J2EE表单的身份验证&#xff0c;则会话超时后应将正常请求重定向到登录页面。 但是&#xff0c;如果您的请求是AJAX…

linux常见命令搜集

查找根目录下txt和pdf文件 find / \( -name "*.txt" -o -name "*.pdf" \) -print 正则查找根目录下所有的txt和pdf文件 find / -regex ".*\(\.txt|\.pdf\)$"查找所有非txt文本 find . ! -name "*.txt" -print制定搜索深度 find ~ -max…

前端html,css基础总结

0.1、css引入界面的方式: 内联式:通过标签的style属性&#xff0c;在标签上直接写样式。 <div style"width:100px; height:100px; background:red "></div> 嵌入式:通过style标签&#xff0c;在网页上创建嵌入的样式表。 <style type"text/css&q…