Guava EventBus 使用
EventBus 是 Google Guava 提供的消息发布-订阅类库,是设计模式中的观察者模式(生产/消费者编程模型)的优雅实现,消息通知负责人通过 EventBus 去注册/注销观察者,最后由消息通知负责人给观察者发布消息。
对于事件监听和发布订阅模式,EventBus 是一个非常优雅和简单解决方案,我们不用创建复杂的类和接口层次结构。
基本用法
创建事件监听器-Listener
我们只需要在指定的方法上加上 @Subscribe
注解就可以使其变成一个 Listener,这样便能订阅消息了。
/**
* SimpleListener 监听器
*/
public class SimpleListener {
/**
* 一个简单的 Listener 方法,监听 String 类型的消息
*/
@Subscribe
public void handle(String event){
System.out.println("String message: " + event);
}
}
创建 EventBus 推送消息
创建 EventBus 事件总线,注册事件监听器,并推送消息。
public class SimpleEventBusMain {
public static void main(String[] args) {
final EventBus eventBus = new EventBus();
// 注册事件监听器
eventBus.register(new SimpleListener());
// 向订阅者发送消息
eventBus.post("Hello EventBus");
}
}
输出结果
String message: Hello EventBus
多事件类型的监听
只需要在要订阅消息的方法上加上 @Subscribe
注解就可以实现对多个不同消息的监听。并且, EventBus 会根据方法参数类型的不同,分别向不同的订阅者 Subscribe 推送不同的消息。参数类型不同,订阅者就不同。
创建 EventBus
/**
* JobEventBusCenter
*/
public final class JobEventBusCenter {
private static class JobEventBus {
private static final EventBus EVENT_BUS = new EventBus();
}
public static void register(JobEventListener<?> listener) {
JobEventBus.EVENT_BUS.register(listener);
}
public static void post(JobEvent<?> event) {
JobEventBus.EVENT_BUS.post(event);
}
}
创建不同的消息事件
- 抽象 JobEvent 类
/**
* JobEvent
*/
public abstract class JobEvent<T> extends EventObject {
public JobEvent(T source) {
super(source);
}
@Override
public T getSource() {
return (T) super.getSource();
}
}
- JobEventString 类,String 类型的消息事件
/**
* String 类型的消息对象
*/
public class JobEventString extends JobEvent<String> {
public JobEventString(String source) {
super(source);
}
@Override
public String getSource() {
return super.getSource();
}
}
- JobEventInteger 类,Integer 类型的消息事件
/**
* Integer 类型的消息对象
*/
public class JobEventInteger extends JobEvent<Integer> {
public JobEventInteger(Integer source) {
super(source);
}
@Override
public Integer getSource() {
return super.getSource();
}
}
创建事件监听器
- JobEventListener 接口
/**
* 事件监听器接口
*/
public interface JobEventListener<T> {
void handle(T event);
}
- JobEventStringListener 类,用于监听 String 类型的消息
/**
* JobEventStringListener
*/
public class JobEventStringListener implements JobEventListener<JobEventString> {
@Override
@Subscribe
public void handle(JobEventString event) {
String source = event.getSource();
System.out.println("String message: " + source);
}
}
- JobEventIntegerListener 类,用于监听 Integer 类型的消息
/**
* JobEventIntegerListener
*/
public class JobEventIntegerListener implements JobEventListener<JobEventInteger> {
@Override
@Subscribe
public void handle(JobEventInteger event) {
Integer source = event.getSource();
System.out.println("Integer message: " + source);
}
}
创建 EventBus
- JobEventBusCenter 类,封装 EventBus 的功能
/**
* JobEventBusCenter
*/
public final class JobEventBusCenter {
private static class JobEventBus {
private static final EventBus EVENT_BUS = new EventBus();
}
public static void register(JobEventListener<?> listener) {
JobEventBus.EVENT_BUS.register(listener);
}
public static void post(JobEvent<?> event) {
JobEventBus.EVENT_BUS.post(event);
}
}
- EventBusMain 类
/**
* EventBusMain
*/
public class EventBusMain {
public static void main(String[] args) {
JobEventIntegerListener integerListener = new JobEventIntegerListener();
JobEventStringListener stringListener = new JobEventStringListener();
// 注册事件监听器
JobEventBusCenter.register(integerListener);
JobEventBusCenter.register(stringListener);
// 发送事件
JobEventBusCenter.post(new JobEventString("hello eventBus"));
JobEventBusCenter.post(new JobEventInteger(123));
}
}
输出结果
String message: hello eventBus
Integer message: 123
继承关系的 Event
如果 Listener A 监听 Event A, 而 Event A 有一个子类 Event B, 此时 Listener A 将同时接收 Event A 和 B 消息。
- 具有继承关系的两个类
/**
* Animal
*/
public class Animal {
private String name;
public Animal(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/**
* Dog
*/
public class Dog extends Animal {
public Dog(String name) {
super(name);
}
}
- 监听器
/**
* AnimalListener
*/
public class AnimalListener {
@Subscribe
public void handle(Animal animal) {
System.out.println("Animal name: " + animal.getName());
}
@Subscribe
public void handle(Dog dog) {
System.out.println("Dog name: " + dog.getName());
}
}
- 创建 EventBus
public class EventBusMain {
public static void main(String[] args) {
final EventBus eventBus = new EventBus();
// 注册事件监听器
eventBus.register(new AnimalListener());
// 向订阅者发送消息
eventBus.post(new Dog("dingding"));
}
}
Dog name: dingding
Animal name: dingding
注意
- 使用 EventBus 时,监听方法的参数有且只能有一个,必须是引用类型,不能是基本数据类型,如:int 要换成 Integer,long 要缓存 Long 等等;
- 由于 EventBus 是将消息队列放入到内存中的,由 Listener 消费这个消息队列,故系统重启之后,保存或者堆积在队列中的消息丢失。
参考
Guide to Guava’s EventBus:https://www.baeldung.com/guava-eventbus#overview