Guava在guava-libraries中爲咱們提供了事件總線EventBus庫,它是事件發佈訂閱模式的實現,讓咱們能在領域驅動設計(DDD)中以事件的弱引用本質對咱們的模塊和領域邊界很好的解耦設計。git
再也不多的廢話,直奔Guava EventBus主題。首先Guava爲咱們提供了同步事件EventBus和異步實現AsyncEventBus兩個事件總線,他們都不是單例的,官方理由是並不想咱們咱們的使用方式。固然若是咱們想其爲單例,咱們能夠很容易封裝它,一個單例模式保證只建立一個實例就對了。github
下面將以EventBus爲例,AsyncEventBus使用方式與其一致的。編程
訂閱
首先EventBus爲咱們提供了register方法來訂閱事件,Guava在這裏的實現很友好,咱們不須要實現任何的額外接口或者base類,只須要在訂閱方法上標註上@Subscribe和保證只有一個輸入參數的方法就能夠搞定。這樣對於簡單的某些事件,咱們甚至能夠直接安全
new Object() { @Subscribe public void lister(Integer integer) { System.out.printf("%d from int%n", integer); } }
Guava發佈的事件默認不會處理線程安全的,但咱們能夠標註@AllowConcurrentEvents來保證其線程安全異步
發佈
對於事件源,則能夠經過post方法發佈事件。 正在這裏對於Guava對於事件的發佈,是依據上例中訂閱方法的方法參數類型決定的,換而言之就是post傳入的類型和其基類類型能夠收到此事件。例以下例:post
final EventBus eventBus = new EventBus(); eventBus.register(new Object() { @Subscribe public void lister(Integer integer) { System.out.printf("%s from int%n", integer); } @Subscribe public void lister(Number integer) { System.out.printf("%s from Number%n", integer); } @Subscribe public void lister(Long integer) { System.out.printf("%s from long%n", integer); } }); eventBus.post(1); eventBus.post(1L);
在這裏有 Integer,Long,與它們基類Number。咱們發送一個整數數據的時候,或者Integer和Number的方法接收,而Long類型則Long類型和Number類型接受。google
因此博主建議對於每類事件封裝一個特定的事件類型是必要的。線程
DeadEvent
DeadEvent暫時不清楚怎麼翻譯更合意,它描述的是死亡事件,即沒有沒任何訂閱者關心,沒有被處理,以DeadEvent類型參數的方法表示.例如在上例中咱們post一個Object類型,以下:翻譯
final EventBus eventBus = new EventBus(); eventBus.register(new Object() { @Subscribe public void lister(DeadEvent event) { System.out.printf("%s=%s from dead events%n", event.getSource().getClass(), event.getEvent()); } }); eventBus.post(new Object());
更多Guava博文:設計