咱们不少状况下,前台须要从新定义一个ValueObject即VO对象来转换后台的实体对象PO。主要的做用有隐藏不暴露PO的一些属性,前台只需关心展现视图须要的部分属性便可。VO通常要进行传输,所以咱们定义VO通常会实现序列化,以提升对象的传输效率。PO与VO的属性转换,传统比较笨拙的办法固然就是本身手动写一个又一个的getter和setter。相对比较繁琐吧!java
固然开源的apache common util包下有个BeanUtils工具类也能够方便两个实体之间的通用快速转换,但我这里要讲的不是这个。这里要说的是,咱们自定义本身的注解,而后经过指定须要绑定的转换的属性,利用Java的反射机制,实现一种相对比较通用的PO与VO的转换方式。apache
首先,咱们来定义两个注解,主要的思路和做用是标记VO与PO类的绑定,和VO定义的属性中与PO对应的属性的绑定。好了,直接来看看下面自定义注解的实现代码:app
BinEntity.javaide
package org.haycco; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 声明须要绑定的实体注解 * * @author haycco */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface BindEntity { Class<?> value(); }
BindFieldName.java工具
package org.haycco; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 声明须要绑定的属性名注解 * * @author haycco */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface BindFieldName { String value(); }
好了,咱们以上的代码定义了两个注解,接下来写两个简单的PO和VO类。代码以下所示:测试
UserPO.javathis
/** * CopyRright (C) 2013: haycco All Rights Reserved. */ package org.haycco; /** * @author haycco */ public class UserPO { private long id; private String account; private String name; private String password; public UserPO(long id, String account, String name, String password) { this.id = id; this.account = account; this.name = name; this.password = password; } public long getId() { return id; } public void setId(long id) { this.id = id; } public String getAccount() { return account; } public void setAccount(String account) { this.account = account; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
UserVO.java对象
/** * CopyRright (C) 2013: haycco All Rights Reserved. */ package org.haycco; import java.io.Serializable; /** * @author haycco */ @BindEntity(UserPO.class) public class UserVO implements Serializable { private static final long serialVersionUID = -1197093269635543264L; @BindFieldName("id") private Integer id; @BindFieldName("account") private String userName; @BindFieldName("name") private String name; @BindFieldName("password") private String password; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "id=" + id + ", name=" + name + ", userName=" + userName + ", password=" + password; } }
那到接下来看看如何利用Java的反射机制来调用setter和getter方法的具体实现代码:blog
/** * 获取get方法 * * @param objectClass * @param fieldName * @return */ @SuppressWarnings("unchecked") public static Method getGetMethod(Class objectClass, String fieldName) { StringBuffer sb = new StringBuffer(); sb.append("get"); sb.append(fieldName.substring(0, 1).toUpperCase()); sb.append(fieldName.substring(1)); try { return objectClass.getMethod(sb.toString()); } catch (Exception e) { } return null; } /** * 获取set方法 * * @param objectClass * @param fieldName * @return */ @SuppressWarnings("unchecked") public static Method getSetMethod(Class objectClass, String fieldName) { try { Class[] parameterTypes = new Class[1]; Field field = objectClass.getDeclaredField(fieldName); parameterTypes[0] = field.getType(); StringBuffer sb = new StringBuffer(); sb.append("set"); sb.append(fieldName.substring(0, 1).toUpperCase()); sb.append(fieldName.substring(1)); Method method = objectClass.getMethod(sb.toString(), parameterTypes); return method; } catch (Exception e) { e.printStackTrace(); } return null; } /** * 执行set方法 * * @param o * @param fieldName * @param value */ public static void invokeSet(Object o, String fieldName, Object value) { Method method = getSetMethod(o.getClass(), fieldName); try { method.invoke(o, new Object[] { value }); } catch (Exception e) { e.printStackTrace(); } } /** * 执行get方法 * * @param o * @param fieldName * @return */ public static Object invokeGet(Object o, String fieldName) { Method method = getGetMethod(o.getClass(), fieldName); try { return method.invoke(o, new Object[0]); } catch (Exception e) { e.printStackTrace(); } return null; }
此上的代码片段是比较通用的调用setter和getter的方式。那接下来咱们就要定义本身的VO转换器了,为了进一步抽象化通用,这里咱们经过泛型的方式来实现,废话少说吧,直接上全部的VO转换器的代码了。get
ValueObjectTransfer.java
/** * CopyRright (C) 2013: haycco All Rights Reserved. */ package org.haycco; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; /** * VO转换器 * * @author haycco */ @SuppressWarnings("rawtypes") public class ValueObjectTransfer<VO, PO> { public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException { List<UserPO> poList = new ArrayList<UserPO>(); poList.add(new UserPO(1, "first", "Haycco", "1234")); poList.add(new UserPO(2, "second", "Haycco", "2345")); ValueObjectTransfer<UserVO, UserPO> transfer = new ValueObjectTransfer<UserVO, UserPO>(); List<UserVO> voList = transfer.cast(poList, UserVO.class); int j = 0; for (UserVO vo : voList) { System.out.println("*****************************************ValueObject: " + ++j); System.out.println("UserVO: " + vo.toString()); } } /** * 转换PO列表 * * @param poList 须要转换的PO列表 * @param voClass 须要转换后的VO类 * @return * @throws InstantiationException * @throws IllegalAccessException * @throws ClassNotFoundException */ public List<VO> cast(List<PO> poList, Class<VO> voClass) throws InstantiationException, IllegalAccessException, ClassNotFoundException { List<VO> voList = new ArrayList<VO>(); for (PO po : poList) { VO vo = this.cast(po, voClass); voList.add(vo); } return voList; } /** * PO->VO * @param po 须要转换的PO * @param voClass 须要转换后的VO类 * @return * @throws InstantiationException * @throws IllegalAccessException * @throws ClassNotFoundException */ @SuppressWarnings("unchecked") public VO cast(PO po, Class<VO> voClass) throws InstantiationException, IllegalAccessException, ClassNotFoundException { // 判断须要转换的PO是否跟VO所绑定的PO一致 if (!voClass.isAnnotationPresent(BindEntity.class)) { //须要转换的PO与VO所绑定的PO不一致 return null; } // 反射获取VO的实例 VO vo = (VO) ClassLoader.getSystemClassLoader().loadClass(voClass.getName()).newInstance(); // 遍历VO全部声明的属性 for (Field field : voClass.getDeclaredFields()) { Class type = field.getType(); String name = field.getName(); // 判断是否包含声明为BindFieldName注解的属性 if (field.isAnnotationPresent(BindFieldName.class)) { BindFieldName bindFieldName = field.getAnnotation(BindFieldName.class); // 反射调用绑定的PO属性的get方法进行取值 Object value = invokeGet(po, bindFieldName.value()); // 反射调用执行该VO属性的set方法设置值 //TODO 须要完善各类属性类型的转换 if(type.isInstance(value)) { invokeSet(vo, name, value); } } } return vo; } /** * 获取get方法 * * @param objectClass * @param fieldName * @return */ @SuppressWarnings("unchecked") public static Method getGetMethod(Class objectClass, String fieldName) { StringBuffer sb = new StringBuffer(); sb.append("get"); sb.append(fieldName.substring(0, 1).toUpperCase()); sb.append(fieldName.substring(1)); try { return objectClass.getMethod(sb.toString()); } catch (Exception e) { } return null; } /** * 获取set方法 * * @param objectClass * @param fieldName * @return */ @SuppressWarnings("unchecked") public static Method getSetMethod(Class objectClass, String fieldName) { try { Class[] parameterTypes = new Class[1]; Field field = objectClass.getDeclaredField(fieldName); parameterTypes[0] = field.getType(); StringBuffer sb = new StringBuffer(); sb.append("set"); sb.append(fieldName.substring(0, 1).toUpperCase()); sb.append(fieldName.substring(1)); Method method = objectClass.getMethod(sb.toString(), parameterTypes); return method; } catch (Exception e) { e.printStackTrace(); } return null; } /** * 执行set方法 * * @param o * @param fieldName * @param value */ public static void invokeSet(Object o, String fieldName, Object value) { Method method = getSetMethod(o.getClass(), fieldName); try { method.invoke(o, new Object[] { value }); } catch (Exception e) { e.printStackTrace(); } } /** * 执行get方法 * * @param o * @param fieldName * @return */ public static Object invokeGet(Object o, String fieldName) { Method method = getGetMethod(o.getClass(), fieldName); try { return method.invoke(o, new Object[0]); } catch (Exception e) { e.printStackTrace(); } return null; } }
以上就是全部实现代码,利用Java的泛型、注解和反射的方式。须要测试的童鞋,只需执行ValueObjectTransfer.java的main方法便可。这样的方式,在通用性来讲仍是比较灵活的,在VO对象用@BindEntity注解绑定对应的PO类,须要自动赋值的VO属性也只需加上@BindFieldName注解进行标记就能够了,但目前上面的代码只是作到同类型属性的setter和getter。还有待完善各类属性类型值的转换,因为须要浩大的if else代码,各位有兴趣的童鞋,本身去完善吧。