烟台做网站哪里好/营销平台有哪些
在使用ApplicationEvent和Listener快速实现业务解耦中提到了用Spring提供的观察者设计模式完成系统内部逻辑解耦。本文将介绍Google-Guava中的一种消息发布-订阅类库——EventBus。
EventBus 是Google.Guava提供的消息发布-订阅类库,它实现了观察者设计模式,消息通知负责人通过EventBus去注册/注销观察者,最后由消息通知负责人给观察者发布消息。
前提:在pom.xml中引入guava包
<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>27.0-jre</version></dependency>
新建类:
相当于注册中心:注册执行都是通过这个类:
import com.google.common.eventbus.EventBus;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);}}
兴建两个观察者:
import com.google.common.eventbus.Subscribe;public class DataObserver1 { /** * 只有通过@Subscribe注解的方法才会被注册进EventBus * 而且方法有且只能有1个参数 * * @param msg */ @Subscribepublic void func(String msg) {System.out.println("String msg: " + msg); } }
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,导致无法匹配到 */ @Subscribepublic void func(Integer msg) { System.out.println("Integer msg: " + msg); }
}
可以看到通过 @Subscribe注解只能有一个参数,如果是两个参数就会报错,只能有一个参数:
Exception in thread "main" com.google.common.util.concurrent.UncheckedExecutionException: java.lang.IllegalArgumentException: Method public void com.study.eventbus.DataObserver1.func(java.lang.String,java.lang.String) has @Subscribe annotation but has 2 parameters.Subscriber methods must have exactly 1 parameter.at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2050)at com.google.common.cache.LocalCache.get(LocalCache.java:3952)at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:3974)at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4958)at com.google.common.cache.LocalCache$LocalLoadingCache.getUnchecked(LocalCache.java:4964)at com.google.common.eventbus.SubscriberRegistry.getAnnotatedMethods(SubscriberRegistry.java:173)at com.google.common.eventbus.SubscriberRegistry.findAllSubscribers(SubscriberRegistry.java:164)at com.google.common.eventbus.SubscriberRegistry.register(SubscriberRegistry.java:74)at com.google.common.eventbus.EventBus.register(EventBus.java:186)at com.study.eventbus.EventBusCenter.register(EventBusCenter.java:21)at com.study.eventbus.Test.main(Test.java:13)
Caused by: java.lang.IllegalArgumentException: Method public void com.study.eventbus.DataObserver1.func(java.lang.String,java.lang.String) has @Subscribe annotation but has 2 parameters.Subscriber methods must have exactly 1 parameter.at com.google.common.base.Preconditions.checkArgument(Preconditions.java:412)at com.google.common.eventbus.SubscriberRegistry.getAnnotatedMethodsNotCached(SubscriberRegistry.java:184)at com.google.common.eventbus.SubscriberRegistry.access$000(SubscriberRegistry.java:54)at com.google.common.eventbus.SubscriberRegistry$1.load(SubscriberRegistry.java:154)at com.google.common.eventbus.SubscriberRegistry$1.load(SubscriberRegistry.java:151)at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3528)at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2277)at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2154)at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2044)... 10 more
然后编写测试类:
/** * 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 ============="); }
}
总结:
EventBus的使用注意问题:
- 代码可读性很差,项目中使用的时候,从post的地方,查询handle使用,都是使用ide的搜索服务,问题很难定位,不如普通的接口调用方便查询;
- 由于EventBus是将消息队列放入到内存中的,listener消费这个消息队列,故系统重启之后,保存或者堆积在队列中的消息丢失。
作者:jackcooper
链接:https://www.jianshu.com/p/93486a604c34
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。