Guava之EventBus使用总结

PamRVKU 4年前

来自: http://www.cnblogs.com/jack2013/p/5162838.html

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.请大牛对代码进行评价