EventBus是Google.Guava提供的消息发布-订阅类库,它实现了观察者设计模式,消息通知负责人通过EventBus去注册/注销观察者,最后由消息通知负责人给观察者发布消息。
1. 首先使用 maven 依赖:
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
</dependency>
2. 示例代码:
2.1 注册中心代码 EventBusCenter.java
package com.lance.google.event.bus;
import com.google.common.eventbus.EventBus;
/**
* Created by lance 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.2 观察者一的代码 DataObserver1.java
package com.lance.google.event.bus;
import com.google.common.eventbus.Subscribe;
/**
* Created by lance on 2017/1/10.
*/
public class DataObserver1 {
/**
* 只有通过@Subscribe注解的方法才会被注册进EventBus
* 而且方法有且只能有1个参数
*
* @param msg
*/
@Subscribe
public void func(String msg) {
System.out.println("String msg: " + msg);
}
}
2.3 观察者一的代码 DataObserver2.java
package com.lance.google.event.bus;
import com.google.common.eventbus.Subscribe;
/**
* Created by lance 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);
}
}
2.4 代码测试 Test.java
package com.lance.google.event.bus;
/**
* Created by lance 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 =============");
}
}
2.5 输出结果:
============ start ====================
String msg: post string method
Integer msg: 123
============ after unregister ============
String msg: post string method
============ end =============
看,使用起来简单吧!
EventBus的使用注意问题:
1.代码可读性很差,项目中使用的时候,从post的地方,查询handle使用,都是使用ide的搜索服务,问题很难定位,不如普通的接口调用方便查询;
2.由于EventBus是将消息队列放入到内存中的,listener消费这个消息队列,故系统重启之后,保存或者堆积在队列中的消息丢失。
3.google的guava的个版本之间的兼容性也是一个问题,有时候会导致jar冲突导致服务无法启动。如hive使用的是guava 11.0版本,而公司的内部jar使用的是guava 22.0版本,程序启动时出现了java.lang.NoSuchMethodError和ClassNoDef的异常。