在软件开发过程中,对象信息的分享以及相互直接的协作是必须的,困难在于确保对象之间的沟通是有效完成的,而不是拥有成本高度耦合的组件。当对象对其他组件的责任有太多的细节时,它被认为是高度耦合的。当一个应用程序有高度的耦合,维护将变得非常具有挑战,任何变化都将带来涟漪效应。为了解决这一类的软件设计问题,我们就需要基于事件的编程。本篇,我们就来学习Guava 基于事件的编程,Guava EventBus(一)EventBus。
在基于事件的编程中,对象可以订阅/监听特定事件,或发布事件。在Java中,我们已经对事件的监听有了初步的认识,一个事件侦听器是一个对象,其目的是当特定事件发生时得到通知。Guava Cache系列中,我们已经提到了RemovalListener,本篇起,我们将要学习Guava EventBus类,以及它如何作用于发布和订阅的事件。EventBus类将能够提高相互的协作水平,而且几乎没有对象之间的耦合。值得注意的是,EventBus是一个轻量级、进程内发布/订阅的沟通风格,并不用于进程间通信。
本系列的学习中,我们将学习和讨论以下内容:
EventBus 以及 AsyncEventBus类
使用EventBus注册订阅事件和事件通知
使用EventBus发布订阅
根据我们的需要,编写事件处理程序,选择粗粒度或细粒度的事件处理机制
结合EventBus,使用依赖注入框架
EventBus
EventBus类位与com.google.common.eventbus包下,它是Guava基于事件编程,发布/订阅编程范式的重点和基础,在一个非常高的层面,用户将注册EventBus特定事件的通知,发布者将发送事件通过EventBus分发给感兴趣的用户。连续的通知所有用户,更重要的是在任何的代码中都可以很迅速的执行事件处理方法。
创建 EventBus 实例
通过调用EventBus构造函数,我们就可以创建一个EventBus实例:
EventBus eventBus = new EventBus();
我们还可以提供一个可选的字符串参数作为标识符来创建一个EventBus(用于日志记录):
EventBus eventBus1 = new EventBus(TradeAccountEvent.class.getName()) ;
订阅事件
通过以下三个必须的步骤,可以从EventBus接收通知对象:
对象需要定义一个公共方法,只接受一个参数,这个参数标识事件类型的对象有兴趣接收通知。
事件通知暴露的方法必须使用@Subscribe注解。
最后,一个对象注册的EventBus实例,register注册方法,本身作为一个参数传递给EventBus。
发布事件
想要发布事件,我们需要向EventBus.post方法传递一个event对象,EventBus将调用订阅者注册处理程序方法,分配带有事件对象类型的参数。这是非常强大的设计概念,包含了接口、超类、实现超类的接口等,这意味着我们可以很容易的,使我们的事件处理程序,变成我们想要的细粒度,只需要通过改变类型接受的事件处理方法。
定义处理方法
用于事件处理程序的方法,必须只接受一个事件对象参数,如前所述,EventBus将连续调用事件处理方法,所以保证这些方法快速完成显得尤为重要。如果需要做任何扩展处理的接收事件,最好是在一个单独的线程运行该代码。
并发性
EventBus不会从多个线程调用处理程序方法,除非使用@AllowConcurrentEvent注释处理程序方法。通过@AllowConcurrentEvent注解注释处理方法,我们断言处理程序方法是线程安全的。使用@AllowConcurrentEvent注释的处理程序方法,本身不会在EventBus中注册。