事件监听处理小框架

来源:互联网 发布:蒙古音乐软件 编辑:程序博客网 时间:2024/04/30 23:01

1、定义注解类

Java代码 复制代码
  1. import java.lang.annotation.ElementType;   
  2. import java.lang.annotation.Retention;   
  3. import java.lang.annotation.RetentionPolicy;   
  4. import java.lang.annotation.Target;   
  5.   
  6. @Target(ElementType.METHOD)       
  7. @Retention(RetentionPolicy.RUNTIME)   
  8. public @interface HandleEvent {   
  9.     Class<? extends BaseEvent>[] events();   
  10. }  



2、在顶层接口IBaseService增加一个方法getRealClass,此方法用于返回真正的业务类字节码引用,此方法在抽象业务类用统一实现即可。本来不需要此方法,但由于使用了SPRING的AOP,一时没有找到取得真正业务类字节码引用的方法,所以才定义这么个接口,代码

Java代码 复制代码
  1. /**  
  2.  * 业务层顶层接口,自定义的小框架里可以在顶层业务接口中直接继承事件接口,不影响性能  
  3.  * 因为在初始化事件监听器时,已经过滤了没有真正实现接口方法的类,所以不会造成多余的调用  
  4.  */  
  5. public interface IBaseService extends IBaseEventListener{   
  6.     public Class<? extends IBaseService> getRealClass();   
  7. }  


抽象业务类的代码

Java代码 复制代码
  1. /**  
  2.  * 实现顶层接口的抽象类  
  3.  */  
  4. public abstract class AbstractBaseService implements IBaseService{   
  5.     /**  
  6.      * 发布事件 2008-9-18  
  7.      */  
  8.     protected void publishEvent(BaseEvent event) {   
  9.         EventController.publishEvent2(event);   
  10.     }   
  11.     //具体子类中不需要再实现   
  12.     public Class<? extends IBaseService> getRealClass(){   
  13.         return this.getClass();   
  14.     }   
  15.        
  16.     public void onBaseEvent(BaseEvent event){   
  17.         //这里空实现,且没有注解,这样,如果具体业务类没有重写方法,   
  18.         //初始化事件监听器时就会被过滤掉,不会造成多余调用   
  19.     }   
  20. }  



改写IBaseEventListener接口,删除getEventClasses方法,因为使用注解来定义要处理事件,所以此方法不再需要。本来onBaseEvent方法也可以去除,直接由注解来定义即可,但由于以下原因,还是要保留:1、如果没有任何接口定义onBaseEvent方法,那么SPRING的代理类也不会有此方法,这样就无法使用AOP的种种好处了;2、为规范事件处理的方法名和参数,更易于后续维护,所以还是要有个接口定义为好。

Java代码 复制代码
  1. /**  
  2.  * 事件处理接口,实现此接口并且getEventClasses方法的返回结果条数大于0,方可处理对应的事件  
  3.  */  
  4. public interface IBaseEventListener {   
  5.     /**  
  6.      * 事件处理的方法  
  7.      */  
  8.     public void onBaseEvent(BaseEvent event);   
  9. }  



事件处理工具类

Java代码 复制代码
  1. /**  
  2.  * 事件处理相关操作工具类  
  3.  */  
  4. public class EventController {   
  5.     private static Map<String,List<LisenerInfo>> listeners2 = new LinkedHashMap<String, List<LisenerInfo>>();   
  6.     /**  
  7.      * 扫瞄所有bean,进行事件监听  
  8.      */  
  9.     public static void initBaseEventListener2(){   
  10.         //取得所有业务类   
  11.         Map<String,IBaseService> beans = SysContext.getBeansOfType(IBaseService.class);   
  12.         if(beans==null || beans.size()==0)   
  13.             return;   
  14.         Collection<IBaseService> values = beans.values();   
  15.         for (IBaseService listener : values) {   
  16.             //注意这里不能使用listener.getClass()方法,因此方法返回的只是SPRING的代理类,此代理类的方法没有注解信息   
  17.             Method[] methods = listener.getRealClass().getDeclaredMethods();   
  18.             for (Method method : methods) {   
  19.                  //判断方法中是否有指定注解类型的注解      
  20.                 boolean hasAnnotation = method.isAnnotationPresent(HandleEvent.class);       
  21.                 if (hasAnnotation) {   
  22.                     //根据注解类型返回方法的指定类型注解      
  23.                     HandleEvent annotation = method.getAnnotation(HandleEvent.class);       
  24.                     Class<? extends BaseEvent>[] events = annotation.events();   
  25.                     if(events==null || events.length==0){//这里过滤掉没有真正实现事件监听的业务类   
  26.                         continue;   
  27.                     }   
  28.                     for (int i = 0; i < events.length; i++) {   
  29.                         try {   
  30.                             if(listeners2.containsKey(events[i].getName())){   
  31.                                 //注意这里要用代理类的方法,即listener.getClass().getMethod(method.getName()),不能直接使用method变量,下同   
  32.                                 listeners2.get(events[i].getName()).add(new LisenerInfo(listener,listener.getClass().getMethod(method.getName())));   
  33.                             }else{   
  34.                                 listeners2.put(events[i].getName(),Arrays.asList(new LisenerInfo[]{new LisenerInfo(listener,listener.getClass().getMethod(method.getName()))}));   
  35.                             }   
  36.                         } catch (Exception e) {   
  37.                             throw new UnknowException("初始化事件监听器时出错:",e);   
  38.                         }   
  39.                     }   
  40.                 }   
  41.             }   
  42.         }   
  43.     }   
  44.     /**  
  45.      * 发布事件  
  46.      */  
  47.     public static void publishEvent2(BaseEvent event){   
  48.         List<LisenerInfo> list = listeners2.get(event.getClass().getName());   
  49.         if(list!=null && list.size()>0){   
  50.             for (LisenerInfo listener : list) {   
  51.                 try {   
  52.                     listener.getMethod().invoke(listener.getService(), event);   
  53.                 } catch (Exception e) {   
  54.                     //此处不能捕捉异常,因为任何一个处理类实例出错都应该全部回滚   
  55.                     throw new UnknowException(e);   
  56.                 }    
  57.             }   
  58.         }   
  59.     }   
  60. }   
  61.   
  62. //此类记录目标方法和目标类   
  63. class LisenerInfo{   
  64.     private Method method;//目标方法   
  65.     private Object service;//业务类实例   
  66.     public LisenerInfo(Object service,Method method){   
  67.         this.method = method;   
  68.         this.service = service;   
  69.     }   
  70.     public Method getMethod() {   
  71.         return method;   
  72.     }   
  73.     public Object getService() {   
  74.         return service;   
  75.     }   
  76. }  



好了,框架完成,事件发布还和以前那样,来看看事件处理的实现,同样也不再需要getEventClasses方法了

Java代码 复制代码
  1. //不再需要每个具体业务都实现IBaseEventListener接口   
  2. public class OtherServiceImpl extends AbstractBaseService implements OtherService{      
  3.     private IBaseDAO otherDao;      
  4.      
  5.     /**    
  6.      * 重写父类的方法,处理用户删除事件    
  7.      */  
  8.     @HandleEvent(events={UserDeleteEvent.class,UserUpdateEvent.class})   
  9.     public void onBaseEvent(BaseEvent baseEvent){      
  10.         if(baseEvent instanceof UserDeleteEvent){//如果是用户删除事件      
  11.             otherDao.deleteOtherData(((User)baseEvent.getSource()).getId());      
  12.         }else{   
  13.             //....   
  14.         }   
  15.     }      
原创粉丝点击