zoukankan      html  css  js  c++  java
  • EventBus使用详解的

    在使用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 
         */  
        @Subscribe
        public 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,导致无法匹配到 
         */  
        @Subscribe
        public 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
    来源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

    世界上所有的不公平都是由于当事人能力不足造成的.
  • 相关阅读:
    Git 使用juju
    svn Q&A
    ubuntu 常用命令
    java中set的交集、差集、并集的简单实现
    java 读写JSON(一)
    java类型转化之SimpleDateFormat-时间转化
    maven 基本常识以及命令
    maven遇到的问题
    java编程思想,对象导论
    条目5:避免创建不必要的对象
  • 原文地址:https://www.cnblogs.com/javayida/p/13346869.html
Copyright © 2011-2022 走看看