浏览 3790 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (1) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-07-24
需求如下:有两个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); 好了,上面就是范型和注解的具体应用,具体代码大家请参见附件中的代码,欢迎与我一起讨论。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间: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); |
|
返回顶楼 | |
发表时间: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; 有问题欢迎与我讨论。 |
|
返回顶楼 | |
发表时间:2009-07-29
我的意思是
IdRetriever3<User,String,Id> ui = new IdRetrieverImpl3<User,String,Id>(); 这句话,已经把String和Id这两个类型具体化了, |
|
返回顶楼 | |
发表时间:2009-07-29
泛型只是在定义的时候定义成模板,
泛型最开始出现在c++里,在c++里叫模板 |
|
返回顶楼 | |
发表时间:2009-07-29
summeryhrb 写道 泛型只是在定义的时候定义成模板,
泛型最开始出现在c++里,在c++里叫模板 主流语言里泛型最早是在Ada里出现的吧,C++还没见影 |
|
返回顶楼 | |
发表时间:2009-08-03
summeryhrb 写道 我的意思是
IdRetriever3<User,String,Id> ui = new IdRetrieverImpl3<User,String,Id>(); 这句话,已经把String和Id这两个类型具体化了, 这里的String和Id只是定义返回类型和annatation类型的模板,非具体化。声明Id的类型只是让这个方法能应用于更多的annation,如@Id、@Content |
|
返回顶楼 | |