`

自己做的事件监听处理小框架(注解版实现)

阅读更多
3、注解版实现:
1、定义注解类
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)    
@Retention(RetentionPolicy.RUNTIME)
public @interface HandleEvent {
	Class<? extends BaseEvent>[] events();
}


2、在顶层接口IBaseService增加一个方法getRealClass,此方法用于返回真正的业务类字节码引用,此方法在抽象业务类用统一实现即可。本来不需要此方法,但由于使用了SPRING的AOP,一时没有找到取得真正业务类字节码引用的方法,所以才定义这么个接口,代码
/**
 * 业务层顶层接口,自定义的小框架里可以在顶层业务接口中直接继承事件接口,不影响性能
 * 因为在初始化事件监听器时,已经过滤了没有真正实现接口方法的类,所以不会造成多余的调用
 */
public interface IBaseService extends IBaseEventListener{
	public Class<? extends IBaseService> getRealClass();
}

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


改写IBaseEventListener接口,删除getEventClasses方法,因为使用注解来定义要处理事件,所以此方法不再需要。本来onBaseEvent方法也可以去除,直接由注解来定义即可,但由于以下原因,还是要保留:1、如果没有任何接口定义onBaseEvent方法,那么SPRING的代理类也不会有此方法,这样就无法使用AOP的种种好处了;2、为规范事件处理的方法名和参数,更易于后续维护,所以还是要有个接口定义为好。
/**
 * 事件处理接口,实现此接口并且getEventClasses方法的返回结果条数大于0,方可处理对应的事件
 */
public interface IBaseEventListener {
	/**
	 * 事件处理的方法
	 */
	public void onBaseEvent(BaseEvent event);
}


事件处理工具类
/**
 * 事件处理相关操作工具类
 */
public class EventController {
	private static Map<String,List<LisenerInfo>> listeners2 = new LinkedHashMap<String, List<LisenerInfo>>();
	/**
	 * 扫瞄所有bean,进行事件监听
	 */
	public static void initBaseEventListener2(){
		//取得所有业务类
		Map<String,IBaseService> beans = SysContext.getBeansOfType(IBaseService.class);
		if(beans==null || beans.size()==0)
			return;
		Collection<IBaseService> values = beans.values();
		for (IBaseService listener : values) {
			//注意这里不能使用listener.getClass()方法,因此方法返回的只是SPRING的代理类,此代理类的方法没有注解信息
			Method[] methods = listener.getRealClass().getDeclaredMethods();
	        for (Method method : methods) {
	             //判断方法中是否有指定注解类型的注解   
	            boolean hasAnnotation = method.isAnnotationPresent(HandleEvent.class);    
	            if (hasAnnotation) {
	                //根据注解类型返回方法的指定类型注解   
	            	HandleEvent annotation = method.getAnnotation(HandleEvent.class);    
	            	Class<? extends BaseEvent>[] events = annotation.events();
	            	if(events==null || events.length==0){//这里过滤掉没有真正实现事件监听的业务类
	            		continue;
	            	}
	            	for (int i = 0; i < events.length; i++) {
	            		try {
		            		if(listeners2.containsKey(events[i].getName())){
		            			//注意这里要用代理类的方法,即listener.getClass().getMethod(method.getName()),不能直接使用method变量,下同
								listeners2.get(events[i].getName()).add(new LisenerInfo(listener,listener.getClass().getMethod(method.getName())));
		            		}else{
		            			listeners2.put(events[i].getName(),createList(new LisenerInfo(listener,listener.getClass().getMethod(method.getName()))));
		            		}
	            		} catch (Exception e) {
							throw new UnknowException("初始化事件监听器时出错:",e);
						}
					}
	            }
			}
		}
	}

private static List<LisenerInfo> createList(LisenerInfo li){
		List<LisenerInfo> list = new ArrayList<LisenerInfo>(5);
		list.add(li);
		return list;
	}

	/**
	 * 发布事件
	 */
	public static void publishEvent2(BaseEvent event){
		List<LisenerInfo> list = listeners2.get(event.getClass().getName());
		if(list!=null && list.size()>0){
			for (LisenerInfo listener : list) {
				try {
					listener.getMethod().invoke(listener.getService(), event);
				} catch (Exception e) {
					//此处不能捕捉异常,因为任何一个处理类实例出错都应该全部回滚
					throw new UnknowException(e);
				} 
			}
		}
	}
}

//此类记录目标方法和目标类
class LisenerInfo{
	private Method method;//目标方法
	private Object service;//业务类实例
	public LisenerInfo(Object service,Method method){
		this.method = method;
		this.service = service;
	}
	public Method getMethod() {
		return method;
	}
	public Object getService() {
		return service;
	}
}


好了,框架完成,事件发布还和以前那样,来看看事件处理的实现,同样也不再需要getEventClasses方法了
//不再需要每个具体业务都实现IBaseEventListener接口
public class OtherServiceImpl extends AbstractBaseService implements OtherService{   
    private IBaseDAO otherDao;   
  
    /**  
     * 重写父类的方法,处理用户删除事件  
     */
    @HandleEvent(events={UserDeleteEvent.class,UserUpdateEvent.class})
    public void onBaseEvent(BaseEvent baseEvent){   
        if(baseEvent instanceof UserDeleteEvent){//如果是用户删除事件   
            otherDao.deleteOtherData(((User)baseEvent.getSource()).getId());   
        }else{
        	//....
        }
    }   
}  


全部完成
2
0
分享到:
评论

相关推荐

    spring 事件监听 3种方式

    在Spring框架中,事件监听是一种实现模块间解耦的有效手段,它允许我们在应用程序的不同部分之间传递消息,而无需直接依赖。本篇文章将详细介绍Spring事件监听的三种方式:基于接口的监听器、基于类的监听器以及基于...

    手动实现的简单Spring框架

    8. **事件监听**:Spring框架允许通过监听器接口来响应容器内的事件,如bean的创建和销毁。手动实现的版本可能会包含类似的事件触发和处理机制。 通过这个项目,开发者可以深入了解Spring框架的内部工作原理,这...

    ssm企业级框架精简版本,纯注解,绝对原创(最新版本,之前连接失效了)

    在本精简版中,开发者宣称已将框架进行了优化,去除了不必要的复杂性,并采用了纯注解的方式,旨在提供一个更加简洁、易于上手的环境。 首先,Spring框架是核心,它提供了依赖注入(DI)和面向切面编程(AOP)的功能。...

    Spring + struts +hibernate(SSHAnnotation) 全注解

    在SSH全注解版中,Hibernate的注解使得数据库表与Java类的映射更加直观。`@Entity`注解标记实体类,`@Table`定义表名,`@Column`对应列名,`@GeneratedValue`管理自增主键,`@OneToMany`、`@ManyToOne`、`@OneToOne`...

    androidannotations框架最新版

    只需在方法上添加相应的注解,就能实现事件监听,大大减少了事件处理代码。 ### 5. 与 Eclipse 集成 虽然现在许多开发者转向了 Android Studio,但 `eclipse-java-luna` 版本的 Eclipse 仍然是一个可靠的开发环境...

    Android butterknife注解框架

    总之,Android Butter Knife注解框架是提升开发效率和代码质量的一个利器,通过注解的方式简化了UI元素的查找和事件处理,让开发者能更专注于业务逻辑,而不是基础的视图操作。虽然现在有更先进的替代方案,但理解并...

    ZK框架开发手册

    为了实现更高级的客户端UI组合,ZK框架提供了客户端事件监听机制,允许开发者通过JavaScript和ZK的组件模型来进行交互式操作。事件监听、事件触发、事件转发以及事件队列的概念被详细解释,以及如何在MVC(Model-...

    基于全注解方式的SSH基础框架

    ### 基于全注解方式的SSH基础框架解析 #### 概述 本文将详细介绍一个基于Struts2、Spring、Hibernate以及Hibernate Generic DAO构建的基础框架。该框架使用全注解的方式进行配置,并且提供了清晰的包结构和文档,...

    使用AndroidAnnotations框架优雅地实现ListView功能例子源代码

    本文将详细介绍如何利用AndroidAnnotations框架优雅地实现ListView功能。 AndroidAnnotations是一个基于注解的Java库,它通过预编译处理来消除Android开发中的样板代码,提高代码的可读性和可维护性。在本例子中,...

    junit5 监听器工程

    JUnit5是Java编程语言中最流行的单元测试框架之一,它的最新版本带来了许多改进和新特性。在"junit5 监听器工程"中,我们主要关注的是如何利用JUnit5的监听器来收集和处理测试结果。这个压缩包可能包含了所有必要的...

    SSH三大框架整合所需jar包(注解方式)

    SSH三大框架指的是Spring、Struts和Hibernate,它们是Java Web开发中的主流框架,极大地提高了开发效率和代码质量。本文将详细介绍在使用注解方式进行整合时所需的jar包,并提供相关知识背景。 Spring框架是一个...

    hibernate框架官方4.4.0版本下载

    6. **异步事件监听**:4.4.0版本引入了异步事件监听器,允许开发者在不阻塞主线程的情况下执行复杂的业务逻辑,提高应用并发性能。 7. **HQL和JPQL的改进**:在查询语言方面,4.4.0版本修复了许多已知问题,并添加...

    Android-Jet使用注解功能来实现去除一些重复的模板代码

    除了这些基础功能,Jet库可能还包含了其他高级特性,如事件监听的注解处理、依赖注入支持等。例如,我们可以通过`@Click`注解为按钮添加点击事件监听,无需再写匿名内部类。此外,可能还有针对生命周期方法的注解,...

    zk入门.web框架

    3. **eventListener**:在Java代码中定义事件监听器,处理特定事件。 4. **action**:通过`&lt;action&gt;`标签或`@Listen`注解处理动作事件。 **六、学习资料** 除了本文提供的信息外,还有更多官方文档、教程和示例...

    Robotlegs最佳实践

    - **Model**:负责存储和处理数据,可以广播事件,监听框架事件。 - **View**:展示数据,通过Mediators与Model交互。 - **Controller**:管理命令,处理来自View的请求,协调Model和Service。 - **Service**:处理...

    java和ssh注解

    除了上述核心注解,SSH框架还提供了许多其他实用注解,如Spring的@PostConstruct和@PreDestroy用于生命周期管理,Struts 2的@ResultType简化结果类型声明,Hibernate的@EntityListeners添加实体监听器等。这些注解...

    androidannotation 开源框架

    这个框架的核心理念是通过注解(Annotations)来替代传统的XML配置,实现依赖注入、界面回调、事件处理等常见任务的自动化,从而让开发者能够更专注于业务逻辑。 在Android开发中,我们常常需要手动编写大量的初始...

    Spring Actionscript IOC 框架与 Flex Cairngorm MVC 应用开发

    Spring Actionscript 是一个针对 Actionscript3 设计的轻量级框架,其灵感来源于 Java 平台上的 Spring 框架,旨在实现控制反转(IOC)以降低组件间的耦合度。 **Spring Actionscript 框架的核心功能** 1. **IOC ...

Global site tag (gtag.js) - Google Analytics