`
jakoes
  • 浏览: 69032 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

[原创][Annation、范型和反射的具体应用]属性获取器

阅读更多
   范型和Annation是JDK 1.5的新特性,好多朋友对他感到非常陌生,只是在应用层面上使用它们。下面我们会对一个特定需求,分三个部分来写一个自己的范型和Annation。

   需求如下:有两个Annotaion:@Id,@Content,它可以应用在任何JavaBean的属性(Field)上,我们要写一个小程序,来获取指定JavaBean的标注了@Id类型的属性的值,接口如下:

public interface IdRetriever<T> {

    /**
     * 获取实体的属性值
     * 
     * @param entity 实体
     * @return
     * @throws Exception
     * @author	jakoes.wu <br>
     * @mail   wujianchao@hongguaninfo.com <br>
     * @create	2009-7-24 <br>
     * @update	2009-7-24 <br>
     * @version	1.0<br>
     * @desc <br>
     */
    public String getId(T entity) throws Exception;
}


输入一个JavaBean,获取JavaBean中标注了@Id的属性的值,部分实现如下:

    首先,我们获取标注了@Id的那个属性:
 private Field getIdField(Class clazz) throws Exception{
	
	Field result = null;
	Field[] fields = clazz.getDeclaredFields();
	for(Field field:fields){
	    
	    if(field.isAnnotationPresent(Id.class)){
		Id id = field.getAnnotation(Id.class);
		result = field;
	    }
	}
	
	if(result == null){
	    logger.error("该实体类中未找到任何标注@Id的属性");
	    throw new Exception("该实体类中未找到任何标注@Id的属性");
	}
	return result;
    }


拼写getter方法:

	
String fieldName = field.getName();
	String methodName = "get" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);


得到getter方法:

  
 private Method getMethod(String methodName) throws NoSuchMethodException{
	
	Method getterMethod;
	
	try {
	    
	    getterMethod = entityClass.getMethod(methodName);
	} catch (SecurityException e) {
	    logger.error("方法[" + methodName + "]映射出出现安全错误",e);
	    throw e;
	} catch (NoSuchMethodException e) {
	    logger.error("没有这个方法[" + methodName + "]",e);
	    throw e;
	}
	
	return getterMethod;
    }


通过反射,得到值:
String result = (String) getterMethod.invoke(entity, null);


上面只列出了程序片段,具体大家参见的附件中的project


   上面的确实现的我们需求,但有两个限制:
* 1.只能处理Annotaiton为 @Id 类型的
* 2.只能处理Annotation返回值为String类型的

如果属性的值值不为String类型,比如:是Integer或是其它类型的呢,上面的程序就不能胜任了,针对这种情况,我们再做如下修改:



package com.jak.generics.getAnnotationValue;
/**
 *
 * @author	jakoes.wu <br>
 * @create	2009-7-24 <br>
 * @project	java.util <br>
 * @email	wujianchao@hongguaninfo.com
 * @msn		jakoes.wu@hotmail.com
 * @copyright 2009 HongGuan Information. All rights reserved
 * @desc <br>
 * 优化:<br>
 * 1.对Annotion的返回值进行了范型,可以获取返回值为任意类型的
 * 限制:<br>
 * 1.只能处理Annotaiton为 @Id 类型的
 */
public interface IdRetriever2<T,S> {

    /**
     * 获取实体的属性值
     * 
     * @param entity 实体
     * @param resultType 返回值类型
     * @return
     * @throws Exception
     * @author	jakoes.wu <br>
     * @mail   wujianchao@hongguaninfo.com <br>
     * @create	2009-7-24 <br>
     * @update	2009-7-24 <br>
     * @version	1.0<br>
     * @desc <br>
     */
    public S getId(T entity,Class<S> resultType) throws Exception;
}


下面是方法实现:

   
 public S getId(T entity,Class<S> resultType) throws Exception {
	
	init(entity,resultType);
	
	Field field = getIdField(entityClass);
	String fieldName = field.getName(); //属性名称
	String methodName = "get" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1); //属性的getter方法
	
	Method getterMethod = getMethod(methodName);
	S result =  (S)getterMethod.invoke(this.entity, null); //通过反射获取属性的值
	
	return result;
    }


请注意上面的方法,对返回值做了范型,可以返回任意值



   上面的改动只是解决了返回值的问题,但目前只支持@Id一种Annotaion,能不能对Annotaion也做范型呢,我输入什么Annotaion,就给我返回标注了Annotaion的属性的值,回答当然是可以的。
   我们对接口修改如下:
  package com.jak.generics.getAnnotationValue;
/**
 *
 * @author	jakoes.wu <br>
 * @create	2009-7-24 <br>
 * @project	java.util <br>
 * @email	wujianchao@hongguaninfo.com
 * @msn		jakoes.wu@hotmail.com
 * @copyright 2009 HongGuan Information. All rights reserved
 * @desc <br>
 * 优化:
 * 1.可以处理任意Annotaiton类型
 * 2.可以处理Annotation返回值为任意类型的
 */
public interface IdRetriever3<T,R,A> {

    /**
     * 获取实体的属性值
     * 
     * @param entity 实体
     * @param resultType 返回值类型
     * @param annotationType Annotation类型
     * @return
     * @throws Exception
     * @author	jakoes.wu <br>
     * @mail   wujianchao@hongguaninfo.com <br>
     * @create	2009-7-24 <br>
     * @update	2009-7-24 <br>
     * @version	1.0<br>
     * @desc <br>
     */
    public R getValue(T entity,Class<R> resultType,Class<A> annotationType) throws Exception;
}


下面是方法中有改动的地方:

	   
 if(field.isAnnotationPresent((Class<? extends Annotation>)   this.annotationClass)){
		A  id = (A) field.getAnnotation(Id.class);
		result = field;
		
	    }



以下是测试:

	
User u = new User();
	u.setUserId("u-123"); //User的主键的类型为String类型
	u.setUserName("jakoes");
	
	Role r = new Role();
	r.setRoldId(2323); //Role的主键的类型为Integer类型
	r.setRoleName("manager");
	
	//获取标注@Id的值
	IdRetriever3<User,String,Id> ui = new IdRetrieverImpl3<User,String,Id>();
	String userId = ui.getValue(u,String.class,Id.class);
	System.out.println(userId);
	
	IdRetriever3<Role,Integer,Id> ri = new IdRetrieverImpl3<Role,Integer,Id>();
	Integer roleId = ri.getValue(r,Integer.class,Id.class);
	System.out.println(roleId);
	
	//获取标注为@Content的值
	IdRetriever3<User, String, Content> ui2 = new IdRetrieverImpl3<User, String, Content>();
	String userName = ui2.getValue(u, String.class, Content.class);
	System.out.println(userName);
	
	IdRetriever3<Role, String, Content> ri2 = new IdRetrieverImpl3<Role, String, Content>();
	String roleName = ri2.getValue(r, String.class, Content.class);
	System.out.println(roleName);



好了,上面就是范型和注解的具体应用,具体代码大家请参见附件中的代码,欢迎与我一起讨论。
分享到:
评论
6 楼 jakoes 2009-08-03  
summeryhrb 写道
我的意思是
IdRetriever3<User,String,Id> ui = new IdRetrieverImpl3<User,String,Id>();  
这句话,已经把String和Id这两个类型具体化了,


这里的String和Id只是定义返回类型和annatation类型的模板,非具体化。声明Id的类型只是让这个方法能应用于更多的annation,如@Id、@Content
5 楼 ravenex 2009-07-29  
summeryhrb 写道
泛型只是在定义的时候定义成模板,

泛型最开始出现在c++里,在c++里叫模板

主流语言里泛型最早是在Ada里出现的吧,C++还没见影
4 楼 summeryhrb 2009-07-29  
泛型只是在定义的时候定义成模板,

泛型最开始出现在c++里,在c++里叫模板
3 楼 summeryhrb 2009-07-29  
我的意思是
IdRetriever3<User,String,Id> ui = new IdRetrieverImpl3<User,String,Id>();  
这句话,已经把String和Id这两个类型具体化了,
2 楼 jakoes 2009-07-27  
summeryhrb 写道
泛型用的不是太好,
IdRetriever3<User,String,Id> ui = new IdRetrieverImpl3<User,String,Id>();  
    String userId = ui.getValue(u,String.class,Id.class);  
    System.out.println(userId);  


ui.getValue(u,String.class,Id.class);
这个方法应该设计为ui.getValue(u);



第一个版本就是这样设计的,如下:
public String getId(T entity) throws Exception;  

但是这样只能获取指定的annotation,且返回值不能指定。

这个签名可能获取任意的annation的属性值,且可以指定返回值的类型:
public R getValue(T entity,Class<R> resultType,Class<A> annotationType) throws Exception; 


有问题欢迎与我讨论。
1 楼 summeryhrb 2009-07-27  
泛型用的不是太好,
IdRetriever3<User,String,Id> ui = new IdRetrieverImpl3<User,String,Id>();  
    String userId = ui.getValue(u,String.class,Id.class);  
    System.out.println(userId);  


ui.getValue(u,String.class,Id.class);
这个方法应该设计为ui.getValue(u);

相关推荐

    C++ 设计新思维:范型编程与设计模式之应用.pdf

    C++ 设计新思维 范型编程与设计模式之应用 pdf

    C++多范型设计

    他还阐述了模板与STL(标准模板库)的关系,解释了如何通过模板来创建自定义容器和迭代器。 在《C++多范型设计》中,作者还探讨了模板与C++其他重要特性的交互,如模板与继承、模板与异常处理、模板与RTTI(运行时...

    范型编程与设计模式之应用

    8. **STL(Standard Template Library,标准模板库)**:STL是C++中范型编程的重要应用,包括容器(如vector、list、set等)、迭代器、算法和函数对象。STL的使用极大地提高了代码的可读性和效率。 9. **模板偏特化...

    范型程序设计与 STL.pdf

    《范型程序设计与 STL》是一本深入探讨C++编程中的关键概念和技术的书籍,主要聚焦于范型(Generic Programming)和标准模板库(Standard Template Library,简称STL)。范型编程是一种强大的软件开发方法,它允许...

    论文研究-消息传递范型与C/S范型双范型的主数据管理机制 .pdf

    本文提出的基于消息传递范型和客户机/服务器(Client/Server,简称C/S)范型双范型的主数据管理机制,能够有效解决MDM面临的问题。 消息传递范型是计算机科学中的一个基本概念,用于描述进程间通信的方式。在这范型...

    《分布式系统原理与范型》.pdf

    《分布式系统原理与范型》作为一本系统介绍分布式系统基本原理与实践应用的书籍,涵盖了分布式系统设计与实现的核心理念。分布式系统指的是由多个可以独立运行的计算单元构成的系统,这些计算单元通过通信网络相互...

    C++ 设计新思维:范型编程与设计模式之应用

    《C++ 设计新思维:范型编程与设计模式之应用》是一本深入探讨C++编程技巧和设计理念的专业书籍,特别关注了范型编程和设计模式在实际开发中的应用。这本书旨在帮助读者提升C++编程的灵活性、可重用性和效率,通过...

    范型和仿函数在桌面系统中的应用

    标题和描述均提到了“范型和仿函数在桌面系统中的应用”,这表明文章的核心将围绕这两个概念在桌面编程环境下的使用展开。虽然标签部分没有提供额外信息,但结合部分内容,我们可以深入探讨范型(Generics)和仿函数...

    c++范型编程与设计模式应用

    《C++范型编程与设计模式应用》是一本旨在帮助开发者从初级阶段过渡到高级阶段的书籍,专注于C++中的泛型编程和设计模式。这本书深入探讨了如何利用C++的泛型特性来编写可复用、高效且灵活的代码,并结合设计模式,...

    c++ 设计新思维:范型编程与设计模式之应用

    《C++ 设计新思维:范型编程与设计模式之应用》是一本深入探讨C++编程技巧和设计理念的专业书籍。本书旨在帮助读者理解和掌握C++中的范型编程(Generic Programming)以及设计模式(Design Patterns)的应用,从而...

    C++多范型设计 作者:[美]James O.Coplien

    在读完这本书以后,读者将会了解如何根据应用领域的共同性和差异性分析来确定C++方案领域的结构,也就是如何选择适用于应用领域同时又为C++所支持的范型来形成方案领域的结构。 全书涵盖了这样一些重要的概念或...

    Java程序设计范型和枚举PPT教案学习.pptx

    范型不仅应用于类,还可以应用于接口和方法。例如,我们可以创建一个泛型方法`&lt;T&gt; void printList(List&lt;T&gt; list)`,这个方法可以接受任何类型列表并打印其内容。在方法内部,`T`可以作为参数类型使用,但必须确保在...

    分布式系统-原理与范型(第2版) 完整版

    第2~9章讨论的是分布式系统的的原理、概念和技术,包括通信、进程、命名、同步化、一致性和复制、容错性以及安全性等,而分布式应用的开发方法(即范型)在第10~13章中进行了讨论。但是,与前一版不同的是,我们...

    分布式系统原理与范型第二版课后习题答案

    分布式系统是一种由多台计算机组成的网络系统,这些计算机在用户看来就像是一个单一的系统。它们通过网络互相通信和协调工作,...通过理解分布式系统原理与范型,可以更好地设计和部署高效、可靠、可维护的分布式应用。

    分布式系统原理与范型

    《分布式系统原理与范型》是分布式系统中的经典教材,全书分为两部分:原理和范型。第一部分详细讨论了分布式系统的原理、概念和技术,其中包括通信、进程、命名、同步、一致性和复制、容错以及安全。第二部分给出了...

    C++ 设计新思维:范型编程与设计模式之应用2

    《C++ 设计新思维:范型编程与设计模式之应用2》这本书深入探讨了C++编程中的两个重要概念——范型编程(Template Programming)和设计模式(Design Patterns)。范型编程是C++中实现泛化的关键机制,而设计模式则是...

    分布式系统原理与范型.pdf

    随后,“原理”部分通过多个章节详细讨论了分布式系统设计中的关键概念和问题,并在“范例”部分通过具体系统范例来展示这些原理如何被应用和实现。这种结构有助于读者系统地理解分布式系统的全貌。 本教材的出版...

    分布式系统原理与范型(第二版)

    分布式系统中的“范型”是指在设计和实现分布式应用时遵循的模式或架构风格。例如: 1. 客户端-服务器(Client-Server)模型:这是最常见的范型,客户端向服务器发送请求,服务器处理并返回结果。这种模型适用于...

Global site tag (gtag.js) - Google Analytics