Guava学习:EventBus

Guava简介

Guava工程包含了若干被Google的 Java项目广泛依赖 的核心库,例如:集合 [collections] 、缓存 [caching] 、原生类型支持 [primitives support] 、并发库 [concurrency libraries] 、通用注解 [common annotations] 、字符串处理 [string processing] 、I/O 等等。其中EventBus是Guava中的事件处理机制,它是设计模式中观察者模式的优雅实现。对于事件监听和发布订阅模式,EventBus是一个非常优雅的解决方案,我们不用创建复杂的类和接口层次结构。

EventBus用法

我们使用Guava之后,如果要订阅消息,只需要在监听者对应的方法加上Subscribe注解。

监听者1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class EventListener {
@Subscribe
// 该注解表示该方法是线程安全的,可以被多个线程同时调用(不加该注解表示该方法同时只能被一个线程调用,同步开销比较大,如果该方法已经是线程安全的,那么建议加上该注解,减少同步开销),必须和Subscribe注解搭配使用
@AllowConcurrentEvents
public void onEvent(String obj) {
System.out.println("obj = " + obj);
}

@Subscribe
// 该注解表示该方法是线程安全的,可以被多个线程同时调用(不加该注解表示该方法同时只能被一个线程调用,同步开销比较大,如果该方法已经是线程安全的,那么建议加上该注解,减少同步开销),必须和Subscribe注解搭配使用
@AllowConcurrentEvents
public void onEvent(Long obj) {
System.out.println("obj = " + obj);
}
}

监听者2

1
2
3
4
5
6
public class EventListener2 {
@Subscribe
public void onEvent(Object obj) {
System.out.println("obj2 = " + obj);
}
}

Dead Event

如果EventBus发送的消息都不是订阅者关心的称之为Dead Event。

监听者

1
2
3
4
5
6
7
8
public class DeadEventListener {
@Subscribe
// 该注解表示该方法是线程安全的,可以被多个线程同时调用(不加该注解表示该方法同时只能被一个线程调用,同步开销比较大,如果该方法已经是线程安全的,那么建议加上该注解,减少同步开销),必须和Subscribe注解搭配使用
@AllowConcurrentEvents
public void onEvent(String obj) {
System.out.println("EventBus 发送了一个所有订阅者都不关心的消息");
}
}

Event的继承

如果Listener A监听Event A,而Event A有一个子类Event B,此时Listener A将同时接收 Event A 和 Event B的消息。

监听者1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class EventListener {
@Subscribe
// 该注解表示该方法是线程安全的,可以被多个线程同时调用(不加该注解表示该方法同时只能被一个线程调用,同步开销比较大,如果该方法已经是线程安全的,那么建议加上该注解,减少同步开销),必须和Subscribe注解搭配使用
@AllowConcurrentEvents
public void onEvent(String obj) {
System.out.println("obj = " + obj);
}

@Subscribe
// 该注解表示该方法是线程安全的,可以被多个线程同时调用(不加该注解表示该方法同时只能被一个线程调用,同步开销比较大,如果该方法已经是线程安全的,那么建议加上该注解,减少同步开销),必须和Subscribe注解搭配使用
@AllowConcurrentEvents
public void onEvent(Long obj) {
System.out.println("long obj = " + obj);
}
}

监听者2

1
2
3
4
5
6
7
8
9
10
11
12
13
public class EventListener2 {
@Subscribe
public void onEvent(Integer obj) {
System.out.println("obj2 = " + obj);
}

@Subscribe
// 该注解表示该方法是线程安全的,可以被多个线程同时调用(不加该注解表示该方法同时只能被一个线程调用,同步开销比较大,如果该方法已经是线程安全的,那么建议加上该注解,减少同步开销),必须和Subscribe注解搭配使用
@AllowConcurrentEvents
public void onEvent(Number obj) {
System.out.println("number obj2 = " + obj);
}
}

测试类及输出结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class GuavaEventBusTest {
public static void main(String[] args) {
// 同步模式
EventBus eventBus = new EventBus("test");
EventListener eventListener = new EventListener();
EventListener2 eventListener2 = new EventListener2();
DeadEventListener deadEventListener = new DeadEventListener();
// 注册listener,监听指定的事件
eventBus.register(eventListener);
eventBus.register(eventListener2);
eventBus.register(deadEventListener);
// 分发事件
eventBus.post("Hello World");

// 注销事件
eventBus.unregister(eventListener);
eventBus.unregister(eventListener2);
eventBus.unregister(deadEventListener);

// 异步模式
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 5, 3, TimeUnit.SECONDS, new LinkedBlockingQueue<>(10));
AsyncEventBus asyncEventBus = new AsyncEventBus("async", threadPoolExecutor);
asyncEventBus.register(eventListener);
asyncEventBus.register(eventListener2);
asyncEventBus.post("Async Hello World!");
asyncEventBus.post(2L);
asyncEventBus.post(3);
asyncEventBus.unregister(eventListener);
asyncEventBus.unregister(eventListener2);
}
}

参考

  1. Guava学习笔记:EventBus - peida - 博客园 (cnblogs.com)

  2. Guava——EventBus消息订阅/分发_蒋含竹的博客-CSDN博客

  3. EventBusExplained · google/guava Wiki · GitHub
显示评论