咱們不少狀況下,前臺須要從新定義一個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代碼,各位有興趣的童鞋,本身去完善吧。