在 使用ApplicationEvent和Listener快速實作業務解耦 中提到了用Spring提供的觀察者設計模式完成系統内部邏輯解耦。本文将介紹Google-Guava中的一種消息釋出-訂閱類庫——EventBus。 EventBus
是Google.Guava提供的消息釋出-訂閱類庫,它實作了觀察者設計模式,消息通知負責人通過EventBus去注冊/登出觀察者,最後由消息通知負責人給觀察者釋出消息。
前提:在pom.xml中引入guava包
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
</dependency>
demo
(1)EventBusCenter.java
package com.lance.google.event.bus;
import com.google.common.eventbus.EventBus;
/**
* Created by zhangzh on 2017/1/10.
*/
public class EventBusCenter {
private static EventBus eventBus = new EventBus();
private EventBusCenter() {
}
public static EventBus getInstance() {
return eventBus;
}
public static void register(Object obj) {
eventBus.register(obj);
}
public static void unregister(Object obj) {
eventBus.unregister(obj);
}
public static void post(Object obj) {
eventBus.post(obj);
}
}
(2) 觀察者1
package com.lance.google.event.bus;
import com.google.common.eventbus.Subscribe;
/**
* Created by zhangzh on 2017/1/10.
*/
public class DataObserver1 {
/**
* 隻有通過@Subscribe注解的方法才會被注冊進EventBus
* 而且方法有且隻能有1個參數
*
* @param msg
*/
@Subscribe
public void func(String msg) {
System.out.println("String msg: " + msg);
}
}
(3) 觀察者2
package com.lance.google.event.bus;
import com.google.common.eventbus.Subscribe;
/**
* Created by zhangzh on 2017/1/10.
*/
public class DataObserver2 {
/**
* post() 不支援自動裝箱功能,隻能使用Integer,不能使用int,否則handlersByType的Class會是int而不是Intege
* 而傳入的int msg參數在post(int msg)的時候會被包裝成Integer,導緻無法比對到
*/
@Subscribe
public void func(Integer msg) {
System.out.println("Integer msg: " + msg);
}
}
(4) Test.java
package com.lance.google.event.bus;
/**
* Created by zhangzh on 2017/1/10.
*/
public class Test {
public static void main(String[] args) throws InterruptedException {
DataObserver1 observer1 = new DataObserver1();
DataObserver2 observer2 = new DataObserver2();
EventBusCenter.register(observer1);
EventBusCenter.register(observer2);
System.out.println("============ start ====================");
// 隻有注冊的參數類型為String的方法會被調用
EventBusCenter.post("post string method");
EventBusCenter.post(123);
System.out.println("============ after unregister ============");
// 登出observer2
EventBusCenter.unregister(observer2);
EventBusCenter.post("post string method");
EventBusCenter.post(123);
System.out.println("============ end =============");
}
}
輸出結果:
String msg: post string method
Integer msg: 123
============ after unregister ============
String msg: post string method
============ end =============
- EventBus的使用注意問題:
- 代碼可讀性很差,項目中使用的時候,從post的地方,查詢handle使用,都是使用ide的搜尋服務,問題很難定位,不如普通的接口調用友善查詢;
- 由于EventBus是将消息隊列放入到記憶體中的,listener消費這個消息隊列,故系統重新開機之後,儲存或者堆積在隊列中的消息丢失。