I choose, I like and keep holding on...
坚持比方法更重要

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

posted on 2016-01-27 12:33  Jack.Kuo  阅读(7194)  评论(0编辑  收藏  举报

不积跬步无以至千里