Guava发布订阅组件EventBus

1,089 阅读3分钟

这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战

Guava是一个谷歌开发的开源库。Guava工程中包含了很多被Google的 Java项目广泛依赖的核心库。 本文主要介绍Guava中的EventBus组件。

EventBus

Eventbus是一种机制,它允许不同的组件在不了解彼此的情况下相互通信。组件可以将Event发送到Eventbus,而不知道谁将接收它,或者有多少其他组件将接收它。组件还可以监听Eventbus上的事件,而不知道是谁发送了事件。这样,组件就可以在不依赖彼此的情况下进行通信。另外,替换一个组件也很容易。只要新组件理解正在发送和接收的Events,其他组件就永远不会知道。

引入依赖

  <dependency>
      <groupId>com.google.guava</groupId>
      <artifactId>guava</artifactId>
      <version>18.0</version>
  </dependency>

快速使用

创建EventBus

使用Eventbus时,首先,为了注册监听器和发布事件,你需要一个总线:

EventBus eventBus=new EventBus();

创建监听器

然后需要创建一个监听器,用于订阅EventBus上的事件。

public class MyEventListener{
	private static int numberEvents;
	private static List<String> eventsList=new ArrayList<>();
	@Subscribe
	public void myEvent(String event) {
		System.out.println(event);
		numberEvents++;
 }

注册监听器并发布事件

可以看到,处理程序方法使用@Subscribe注解;现在Listener应该被添加到Eventbus和发布事件。下面是一个简单的例子:

import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;

public class EventBusTest {

   class EventListener{
      private  int numberEvents;
      @Subscribe
      public void myEvent(String event) {
          System.out.println(event);
          numberEvents++;
      }
      public  int getNumberEvents(){
          return  numberEvents;
      }
	}

	@Test
	public void testEventBusSimpleTest(){
		EventBus eventBus=new EventBus();
		EventListener listener = new EventListener();
		eventBus.register(listener);
		eventBus.post("event1");
		eventBus.post("event2");
		assertEquals(2, listener.getNumberEvents());
	}
}

实际案例

是不是很简单!我们可以通过EventBus解决一些实际场景中的问题,在单个JVM中进行异步处理。比如在一些交易系统中,在付款成功以后,需要将结果通知给付款方,同时也要通知收款方。

在这个例子中,我们需要两个监听器,一个用于发送付款成功的消息给用户,一个用于发送消息给收款方。

首先有一个用于表示交易的类。

class Transaction {
    private final String transactionName;
    private double amount = 0.0;
    public Transaction(String transactionName, Double amount) {
        this.transactionName = transactionName;
        this.amount = amount;
    }
    public String getTransactionName() {
        return transactionName;
    }
    public double getAmount() {
        return amount;
    }
    @Override
    public String toString() {
        return "[transaction with name " + transactionName + " and amount " + amount + "]";
    }
}

然后建立两个监听器,用于监听交易完成的事件,并作出响应。

class SendPaymentListener {
    @Subscribe
    private void sendToPayment(Transaction transaction) {
        System.out.println("【付款方】交易" + transaction.getTransactionName() + "交易完成,金额:" + transaction.getAmount());
        // to do something...
    }
}

class SendReceiveListener {
    @Subscribe
    private void sendToPayment(Transaction transaction) {
        System.out.println("【收款方】交易" + transaction.getTransactionName() + "交易完成,金额:" + transaction.getAmount());
        // to do something...
    }
}

有了事件的订阅方之后,我们建立EventBus,并将监听器注册在EventBus上,然后将Event发布。

public class PaymentService {

    static class EventBusFactory {
        //create an asynch bus in new Thread
        private static EventBus eventBus
            = new AsyncEventBus(Executors.newCachedThreadPool());
        public static EventBus getEventBus() {
            return eventBus;
        }
    }
    
    @Test
    public void testPayment() {
        //registering listeners
        EventBusFactory.getEventBus().register(new SendPaymentListener());
        EventBusFactory.getEventBus().register(new SendReceiveListener());
        EventBusFactory.getEventBus().post(new Transaction("交易001", 100.0));
    }
}

我们执行测试用例后,结果如下:

可以看出,我们并不用显式的去调用SendPaymentListenerSendReceiveListener的方法,EventBus内部便可以替我们完成事件的发布。

小结

Guava EventBus的内容比较简单,所以上面内容也写的很简单,你可以动手试试,体验一下Guava的发布订阅模式。如果对你有所帮助,点个赞就是对我最大的鼓励!