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
    来源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

    世界上所有的不公平都是由于当事人能力不足造成的.
  • 相关阅读:
    线段树专辑—— pku 1436 Horizontally Visible Segments
    线段树专辑——pku 3667 Hotel
    线段树专辑——hdu 1540 Tunnel Warfare
    线段树专辑—— hdu 1828 Picture
    线段树专辑—— hdu 1542 Atlantis
    线段树专辑 —— pku 2482 Stars in Your Window
    线段树专辑 —— pku 3225 Help with Intervals
    线段树专辑—— hdu 1255 覆盖的面积
    线段树专辑—— hdu 3016 Man Down
    Ajax跨域访问
  • 原文地址:https://www.cnblogs.com/javayida/p/13346869.html
Copyright © 2011-2022 走看看