1.将EventBus封装为单例模式使用
1 packagepriv.jack.demo.listener;2
3 importjava.util.Map;4
5 importcom.google.common.collect.Maps;6 importcom.google.common.eventbus.EventBus;8
9 /**
10 * 事件总线工厂11 * 将EventBus封装为单例模式使用12 *@authorJack13 *14 */
15 public classEventBusFactory {16
17 private volatile staticEventBusFactory INSTANCE ;18
19 /**
20 * 保存已经注册的监听器,防止监听器重复注册21 */
22 private Map> registerListenerContainers =Maps.newConcurrentMap() ;23
24 privateEventBusFactory() {}25
26 public staticEventBusFactory build() {27 if(INSTANCE == null) {28 synchronized (EventBusFactory.class) {29 if(INSTANCE == null) {30 INSTANCE = newEventBusFactory() ;31 }32 }33 }34 returnINSTANCE ;35 }36
37 private final EventBus EVENTBUS = newEventBus() ;38
39 /**
40 * 事件转发41 *@paramevent42 */
43 public voidpostsEvent(SystemEvent event) {44 EVENTBUS.post(event) ;45 }46
47 /**
48 * 监听器注册49 *@paramclazz50 */
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更通用
packagepriv.jack.demo.listener.event;/*** 系统事件父类
*@authorJack
**/
public classSystemEvent {public static final String MEMBER_DELETE_EVENT = "memberDelEvt";public static final String TEST_EVENT = "testEvt";privateString eventName;publicSystemEvent() {
}publicSystemEvent(String eventName) {this.eventName =eventName;
}
@OverridepublicString toString() {return "SystemEvent [eventName=" + eventName + "]";
}publicString getEventName() {returneventName;
}public voidsetEventName(String eventName) {this.eventName =eventName;
}
}
3.编写事件子类
packagepriv.jack.demo.listener.event;public class TestEvent extendsSystemEvent {privateString testField;publicString getTestField() {returntestField;
}public voidsetTestField(String testField) {this.testField =testField;
}publicTestEvent() {}publicTestEvent(String eventName, String testField) {super(eventName) ;this.testField =testField ;
}
}packagepriv.jack.demo.listener.event;importjava.util.List;/*** 成员删除事件
* 该事件触发画面合成修改操作
*@authorJack
**/
public class MemberDeletedEvent extendsSystemEvent{privateString confCreatorToken;private Liste164ListToOper ;private intcmd;publicMemberDeletedEvent() {
}publicMemberDeletedEvent(String eventName) {super(eventName);
}public MemberDeletedEvent(String eventName, String confCreatorToken, List e164ListToOper, intcmd) {this(eventName) ;this.confCreatorToken =confCreatorToken ;this.e164ListToOper =e164ListToOper ;this.cmd =cmd ;
}
@OverridepublicString toString() {return "MemberDeletedEvent [confCreatorToken=" + confCreatorToken + ", e164ListToOper=" + e164ListToOper + ", cmd=" + cmd + "]";
}publicString getConfCreatorToken() {returnconfCreatorToken;
}public voidsetConfCreatorToken(String confCreatorToken) {this.confCreatorToken =confCreatorToken;
}public ListgetE164ListToOper() {returne164ListToOper;
}public void setE164ListToOper(Liste164ListToOper) {this.e164ListToOper =e164ListToOper;
}public intgetCmd() {returncmd;
}public void setCmd(intcmd) {this.cmd =cmd;
}
}
4.编写Listener接口类
public interfaceEventListener {public voidaction(SystemEvent event) ;
}
5.编写Listener实现类
/*** 测试事件监听类
*@authorJack
**/
public class TestEventListener implementsEventListener{private Logger logger = LoggerFactory.getLogger("birdie") ;
@Override
@Subscribe
@AllowConcurrentEventspublic voidaction(SystemEvent event) {
logger.info(String.format("[TestEventListener ] action, listener=%s event=%s", this.toString(), event.toString()));
TestEvent subEvent=(TestEvent) event ;
invoke(subEvent) ;
}public voidinvoke(TestEvent testEvent) {
logger.info(String.format("[TestEventListener ] action testEvent=%s", testEvent.toString()));
}
}/*** 成员删除事件监听器, 支持并发操作
*@seeMemberDeletedEvent
*@seebirdie-web下的EventBusTest
*@authorJack
**/
public class MemberDeletedEventListener implementsEventListener{private Logger logger = LoggerFactory.getLogger("birdie") ;
@Override
@Subscribe
@AllowConcurrentEventspublic voidaction(SystemEvent event) {
logger.info(String.format("[MemberDeletedEventListener ] action event=%s", event.toString()));
MemberDeletedEvent subEvent=(MemberDeletedEvent) event ;
invoke(subEvent) ;
}public voidinvoke(MemberDeletedEvent memberDeletedEvent) {if(MtsOper.MT_DELETE.getOperCode() ==memberDeletedEvent.getCmd()) {
//...业务代码}
}
}
6.单元测试
public classEventBusTest {
//测试重复注册监听器
@Testpublic voidtestRepeatRegister() {final EventBus bus = newEventBus() ;
bus.register(newTestEventListener());
bus.register(newTestEventListener());
TestEvent event= new TestEvent(SystemEvent.TEST_EVENT, "123") ;
bus.post(event);
}
//测试并发操作//@Test
public voidtestConcurrcy() {
List 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(newRunnable() {
@Overridepublic voidrun() {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);
}
//测试继承结构下的事件分发
@Testpublic voidtestInherit() {
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.请大牛对代码进行评价