zoukankan      html  css  js  c++  java
  • Guava之EventBus使用总结

    1.将EventBus封装为单例模式使用

     1 package priv.jack.demo.listener;
     2 
     3 import java.util.Map;
     4 
     5 import com.google.common.collect.Maps;
     6 import com.google.common.eventbus.EventBus; 8 
     9 /**
    10  * 事件总线工厂
    11  * 将EventBus封装为单例模式使用
    12  * @author Jack
    13  *
    14  */
    15 public class EventBusFactory {
    16     
    17     private volatile static EventBusFactory  INSTANCE ;
    18     
    19     /**
    20      * 保存已经注册的监听器,防止监听器重复注册
    21      */
    22     private Map<String, Class<? extends EventListener>> registerListenerContainers = Maps.newConcurrentMap() ;
    23     
    24     private EventBusFactory() {}
    25     
    26     public static EventBusFactory build() {
    27         if(INSTANCE == null) {
    28             synchronized (EventBusFactory.class) {
    29                 if(INSTANCE == null) {
    30                     INSTANCE = new EventBusFactory() ;
    31                 }
    32             }
    33         }
    34         return INSTANCE ;
    35     }
    36     
    37     private final EventBus EVENTBUS = new EventBus() ;
    38     
    39     /**
    40      * 事件转发
    41      * @param event
    42      */
    43     public void postsEvent(SystemEvent event) {
    44         EVENTBUS.post(event) ;
    45     }
    46     
    47     /**
    48      * 监听器注册
    49      * @param clazz
    50      */
    51     public void register(Class<? extends EventListener> clazz)  {
    52         String clazzName = clazz.getSimpleName() ;
    53         if(registerListenerContainers.containsKey(clazzName)) {
    54             return ;
    55         }
    56         try {
    57             registerListenerContainers.put(clazzName, clazz) ;
    58             Object obj = registerListenerContainers.get(clazzName).newInstance();
    59             EVENTBUS.register(obj) ;
    60         } catch (Exception e) {
    61             e.printStackTrace();
    62         } 
    63     }
    64 }

    封装之后,将EventBus的post和register也进行封装

    2.封装SystemEvent作为事件的顶层父类,为了使EventBusFactory的postEvent更通用

    package priv.jack.demo.listener.event;
    
    /**
     * 系统事件父类
     * @author Jack
     *
     */
    public class SystemEvent {
        
        public static final String MEMBER_DELETE_EVENT = "memberDelEvt" ;
        public static final String TEST_EVENT = "testEvt" ;
    
        private String eventName;
        
        public SystemEvent() {
            
        }
        
        public SystemEvent(String eventName) {
            this.eventName = eventName;
        }
        
        @Override
        public String toString() {
            return "SystemEvent [eventName=" + eventName + "]";
        }
    
    
    
        public String getEventName() {
            return eventName;
        }
    
        public void setEventName(String eventName) {
            this.eventName = eventName;
        }
    }

    3.编写事件子类

    package priv.jack.demo.listener.event;
    
    public class TestEvent extends SystemEvent {
    
        private String testField;
    
        public String getTestField() {
            return testField;
        }
    
        public void setTestField(String testField) {
            this.testField = testField;
        }
        
        public TestEvent() {}
        
        public TestEvent(String eventName, String testField) {
            super(eventName) ;
            this.testField = testField ;
        }
    
    }
    
    package priv.jack.demo.listener.event;
    
    import java.util.List;
    
    /**
     * 成员删除事件
     * 该事件触发画面合成修改操作
     * @author Jack
     *
     */
    public class MemberDeletedEvent extends SystemEvent{
    
        private String confCreatorToken;
    
        private List<String> e164ListToOper ;
    
        private int cmd;
        
        public MemberDeletedEvent() {
        }
        
        public MemberDeletedEvent(String eventName) {
            super(eventName);
        }
        
        public MemberDeletedEvent(String eventName, String confCreatorToken, List<String> e164ListToOper, int cmd) {
            this(eventName) ;
            this.confCreatorToken = confCreatorToken ;
            this.e164ListToOper = e164ListToOper ;
            this.cmd = cmd ;
        }
    
        @Override
        public String toString() {
            return "MemberDeletedEvent [confCreatorToken=" + confCreatorToken + ", e164ListToOper=" + e164ListToOper + ", cmd=" + cmd + "]";
        }
    
        public String getConfCreatorToken() {
            return confCreatorToken;
        }
    
        public void setConfCreatorToken(String confCreatorToken) {
            this.confCreatorToken = confCreatorToken;
        }
    
        public List<String> getE164ListToOper() {
            return e164ListToOper;
        }
    
        public void setE164ListToOper(List<String> e164ListToOper) {
            this.e164ListToOper = e164ListToOper;
        }
    
        public int getCmd() {
            return cmd;
        }
    
        public void setCmd(int cmd) {
            this.cmd = cmd;
        }
    
    }

    4.编写Listener接口类

    public interface EventListener {
    
        public void action(SystemEvent event) ;
        
    }

    5.编写Listener实现类

    /**
     * 测试事件监听类
     * @author Jack
     *
     */
    public class TestEventListener implements EventListener{
        
        private Logger logger = LoggerFactory.getLogger("birdie") ;
    
        @Override
        @Subscribe
        @AllowConcurrentEvents
        public void action(SystemEvent event) {
            logger.info(String.format("[TestEventListener ] action, listener=%s event=%s", this.toString(), event.toString()));
            TestEvent subEvent = (TestEvent) event ;
            invoke(subEvent) ;
        }
        
        public void invoke(TestEvent testEvent) {
            logger.info(String.format("[TestEventListener ] action testEvent=%s", testEvent.toString()));
        }
    
    }
    
    
    /**
     * 成员删除事件监听器, 支持并发操作
     * @see MemberDeletedEvent
     * @see birdie-web下的EventBusTest
     * @author Jack
     *
     */
    public class MemberDeletedEventListener implements EventListener{
        
        private Logger logger = LoggerFactory.getLogger("birdie") ;
    
        @Override
        @Subscribe
        @AllowConcurrentEvents
        public void action(SystemEvent event) {
            logger.info(String.format("[MemberDeletedEventListener ] action event=%s", event.toString()));
            MemberDeletedEvent subEvent = (MemberDeletedEvent) event ;
            invoke(subEvent) ;
        }
        
        public void invoke(MemberDeletedEvent memberDeletedEvent) {
            if(MtsOper.MT_DELETE.getOperCode() == memberDeletedEvent.getCmd()) {
                //...业务代码
            }
        }
    
    }

    6.单元测试

    public class EventBusTest {
        
    //测试重复注册监听器 @Test
    public void testRepeatRegister() { final EventBus bus = new EventBus() ; bus.register(new TestEventListener()); bus.register(new TestEventListener()); TestEvent event = new TestEvent(SystemEvent.TEST_EVENT, "123") ; bus.post(event); }
    //测试并发操作
    //@Test public void testConcurrcy() { List<String> list = Lists.newArrayList("001#01") ; MemberDeletedEvent event = new MemberDeletedEvent(SystemEvent.MEMBER_DELETE_EVENT, "123", list , 1) ; for(int i=0 ; i < 100 ; i++) { final int cnt = i ; Thread t = new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("第"+ cnt+ "次"); EventBusFactory.build().register(MemberDeletedEventListener.class) ; } }) ; t.start(); } try { Thread.sleep(6000); } catch (InterruptedException e) { e.printStackTrace(); } EventBusFactory.build().postsEvent(event); }
    //测试继承结构下的事件分发 @Test
    public void testInherit() { TestEvent event = new TestEvent(SystemEvent.TEST_EVENT, "123") ; EventBusFactory.build().register(TestEventListener.class) ; EventBusFactory.build().postsEvent(event); } }

    总结

    1.支持类的继承结构下的事件分发,但子类和父类都能收到事件。

    2.@AllowConcurrentEvents 进行并发设置,经过简单测试是OK的

    相关问题

    1.如何能够很优雅的进行对监听器进行集中且动态的注册,让其可扩展性更好

    目前上面demo的代码是在post之前进行register,并在register中进行重复注册的屏蔽,如果新增监听器的话需要修改代码,可扩展性差

    2.请大牛对代码进行评价

  • 相关阅读:
    Effective C++ 学习一
    JavaScript 定义类和继承类的基本步骤
    Vararg collection Factory Method
    apache之httpd启动、终止、重启小结
    Thinking in C++ 学习笔记[1]
    Creational Pattern 之 Abstract Factory
    Perl WEB 开发之 Template
    C语言博客作业数据类型
    C语言博客作业一二维数组
    C语言博客作业函数
  • 原文地址:https://www.cnblogs.com/jack2013/p/5162838.html
Copyright © 2011-2022 走看看