范型和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);
好了,上面就是范型和注解的具体应用,具体代码大家请参见附件中的代码,欢迎与我一起讨论。
分享到:
相关推荐
C++ 设计新思维 范型编程与设计模式之应用 pdf
范型和仿函数在桌面系统中的应用
深入探讨范型编程思想及C++语言中范型设计的应用
c++范型编程与设计模式应用,脱离菜鸟,进阶高手的一本很好的参考书。
C++多范型设计,ISBN:9787508318240,作者:(美)James O.Coplien著;鄢爱兰,周辉等译;鄢爱兰译
第9章 范型和容器类.ppt第9章 范型和容器类.ppt
消息传递范型与C/S范型双范型的主数据管理机制,陈晓云,邢乔金,本文针对主数据管理(MDM)存在的问题提出了一种基于消息传递机制范型与C/S范型双范型的主数据管理机制,当各个分系统的数据有所变化�
在读完这本书以后,读者将会了解如何根据应用领域的共同性和差异性分析来确定C++方案领域的结构,也就是如何选择适用于应用领域同时又为C++所支持的范型来形成方案领域的结构。 全书涵盖了这样一些重要的概念或...
第2~9章讨论的是分布式系统的的原理、概念和技术,包括通信、进程、命名、同步化、一致性和复制、容错性以及安全性等,而分布式应用的开发方法(即范型)在第10~13章中进行了讨论。但是,与前一版不同的是,我们...
《分布式系统原理与范型》是分布式系统中的经典教材,全书分为两部分:原理和范型。第一部分详细讨论了分布式系统的原理、概念和技术,其中包括通信、进程、命名、同步、一致性和复制、容错以及安全。第二部分给出了...
在实际应用中,如果能够灵活应用范型和反射,那么该Java程序员可以设计出非常好的东西来,从而解决实际开发简化开发过程的目的。比如,在EJB 2.0开发客户端应用时,如果使用范型和反射,可以把EJB 2.0的标准使用...
Java 范型Java 范型
范型程序设计与 STL.pdf,大小约 300K。
《分布式系统原理与范型》第一版.中文版,影印版。
并且通过运用这些模板技术(例如元编程等),实现了多个设计模式的代码框架的自动生成,书不厚,正文内容不过300页,但是书中没有废话,每一章的内容都很精彩,值得仔细推敲和研究,虽然里面有少量错误(有些可能是...
java1.5范型编程指南.docjava1.5范型编程指南.docjava1.5范型编程指南.docjava1.5范型编程指南.docjava1.5范型编程指南.doc
C++ 设计新思维:范型编程与设计模式之应用
分布式系统原理和范型第二版,适合中高级程序员,帮助理解分布式的原理和使用。
分布式系统原理与范型第二版课后习题答案 分布式系统原理与范型第二版课后习题答案 分布式系统原理与范型第二版课后习题答案 分布式系统原理与范型第二版课后习题答案