一、今天剛完成這麼一個功能模塊,需求場景是這樣的,咱們須要對接許多銀行的接口,咱們解析銀行XML報文後,根據每一個銀行每一個接口咱們會解析獲得不少BankDTO; 二、而後咱們須要在BankDTO挑出一些必要的字段放到另一個 ResultDTO 中去,而後將 ResultDTO 的數據入庫處理; 三、並且最關鍵的是,每一個銀行的字段五花八門,咱們根本沒辦法統一字段,最初的辦法咱們是對每一個 BankDTO 寫了一個轉換類轉成 ResultDTO; 四、可是隨着接入的銀行愈來愈多了,開發效率也就慢慢的降下來了,然而我就在思考如何優化這個字段轉換來轉換去的笨重方法; 五、通過展轉反側的思考,最終本身定義一個註解類,而後將這些註解安插在BankDTO上,而咱們須要作的事情就是反射獲取註解值而後給ResultDTO賦值便可; 六、原理就是這麼簡單,這樣寫好以後,銀行一多,開發人員不夠,咱們找些不會開發的人員只要告訴他們如何寫 BankDTO 對象便可,如何映射字段值便可,最後提交代碼就搞定了; 七、而我在這裏主要將一些類貼出來僅供你們參考,若是這種思路在你們工做中用得着的話,相信稍微複用我這思路,功能很快就能水到渠成;
package com.springms.cloud.reflect.util; import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Enumeration; import java.util.List; /** * 反射工具類。 * * @author hmilyylimh * * @version 0.0.1 * * @date 2017/10/24 */ public class ReflectionUtil { private static final org.slf4j.Logger Logger = LoggerFactory.getLogger(ReflectionUtil.class); /** * 循環向上轉型, 獲取對象的 DeclaredField。 * * @param object : 子類對象,也就是實現類對象; * @param fieldName : 父類中的屬性名; * @return 父類中的屬性對象 */ public static Field getDeclaredField(Object object, String fieldName) { Field field = null; Class<?> clazz = object.getClass(); for (; clazz != Object.class; clazz = clazz.getSuperclass()) { try { field = clazz.getDeclaredField(fieldName); return field; } catch (Exception e) { // 這裏甚麼都不要作!而且這裏的異常必須這樣寫,不能拋出去。 // 若是這裏的異常打印或者往外拋,則就不會執行clazz = clazz.getSuperclass(),最後就不會進入到父類中了 // Logger.error("循環向上轉型, 獲取對象的 DeclaredField 異常, fieldName: {}, object: {}, \n\ne: {}", fieldName, object, CommonUtil.getExceptionStackTrace(e)); } } return null; } /** * 循環向上轉型, 獲取當前對象以及父類全部對象的屬性 Field 字段。 * * @param objectClass * @return */ public static List<Field> getDeclaredSuperFields(Class<?> objectClass) { List<Field> declaredFieldList = new ArrayList<Field>(); Class<?> tempClass = objectClass; try { while(true){ if(tempClass == Object.class){ break; } declaredFieldList.addAll(Arrays.asList(tempClass.getDeclaredFields())); tempClass = tempClass.getSuperclass(); } } catch (Exception e) { // 這裏甚麼都不要作!而且這裏的異常必須這樣寫,不能拋出去。 // 若是這裏的異常打印或者往外拋,則就不會執行clazz = clazz.getSuperclass(),最後就不會進入到父類中了 Logger.error("循環向上轉型, 獲取當前對象以及父類全部對象的屬性 Field 字段異常, objectClass: {}, \n\ne: {}", objectClass, e); } return declaredFieldList; } /** * 循環向上轉型, 獲取對象的 DeclaredMethod。 * * @param object : 子類對象,也就是實現類對象; * @param methodName : 父類中的方法名; * @param parameterTypes : 父類中的方法參數類型; * @return 父類中的方法對象 */ public static Method getDeclaredMethod(Object object, String methodName, Class<?>... parameterTypes) { Method method = null; for (Class<?> clazz = object.getClass(); clazz != Object.class; clazz = clazz.getSuperclass()) { try { method = clazz.getDeclaredMethod(methodName, parameterTypes); return method; } catch (Exception e) { // 這裏甚麼都不要作!而且這裏的異常必須這樣寫,不能拋出去。 // 若是這裏的異常打印或者往外拋,則就不會執行clazz = clazz.getSuperclass(),最後就不會進入到父類中了 // Logger.error("循環向上轉型, 獲取對象的 DeclaredMethod 異常, methodName: {}, object: {}, parameterTypes: {}, \n\ne: {}", methodName, object, parameterTypes, CommonUtil.getExceptionStackTrace(e)); } } return null; } /** * 獲取 Field 字段的值。 * * @param field * @param fieldParentObj * @return */ public static Object getFieldValue(Field field, Object fieldParentObj) { Object value = null; try { field.setAccessible(true); value = field.get(fieldParentObj); } catch (Exception e) { Logger.error("獲取 Field 字段的值異常, field: {}, fieldParentObj: {}, \n\ne: {}", field, fieldParentObj, e); } return value; } /** * 設置 Field 字段的值。 * * @param field * @param fieldParentObj * @param newValueObj */ public static void setFieldValue(Field field, Object fieldParentObj, Object newValueObj) { try { field.setAccessible(true); field.set(fieldParentObj, newValueObj); } catch (Exception e) { Logger.error("設置 Field 字段的值異常, field: {}, fieldParentObj: {}, newValueObj: {}, \n\ne: {}", field, fieldParentObj, newValueObj, e); } } /** * 獲取當前對象中子對象的屬性。 * * @param parentObj:當前對象,須要搜索查詢字段所屬的父類對象; * @param searchFieldParentClass:查詢字段所屬字段的父類對象Class類型; * @param searchFieldName:查詢字段名稱; * @return new Object[] { searchFieldParentObject, searchField, searchFieldValue } */ public static Object[] getChildAttr(Object parentObj, Class<?> searchFieldParentClass, String searchFieldName) { if (parentObj == null) { return null; } Class<?> parentObjClass = parentObj.getClass(); Field foundedField = null; Object foundedFieldValue = null; Object[] result = null; try { foundedField = parentObjClass.getDeclaredField(searchFieldName); foundedField.setAccessible(true); foundedFieldValue = foundedField.get(parentObj); return new Object[]{parentObj, foundedField, foundedFieldValue}; } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { // 此處異常捕獲爲:找不到屬性名異常。 // 注意在此處咱們要手工去幫它找到field應該對象到哪一個對象裏的值,由於咱們不知道它們之間的關係,因此須要手工指定關係,找哪一個對象去關聯 result = getChildObjAttr(parentObj, parentObjClass, searchFieldParentClass, searchFieldName); } catch (IllegalArgumentException e) { Logger.error("獲取當前對象中子對象的屬性異常, searchFieldParentClass: {}, searchFieldName: {}, parentObj: {}, \n\ne: " + "{}", searchFieldParentClass, searchFieldName, parentObj, e); } catch (IllegalAccessException e) { Logger.error("獲取當前對象中子對象的屬性異常, searchFieldParentClass: {}, searchFieldName: {}, parentObj: {}, \n\ne: " + "{}", searchFieldParentClass, searchFieldName, parentObj, e); } return result; } /** * 獲取 parentObj 對象中子類對象的屬性。 * * @param parentObj:當前對象,須要搜索查詢字段所屬的父類對象; * @param parentObjClass:當前對象類名稱類型,須要搜索查詢字段所屬的父類類名稱類型; * @param searchFieldParentClass:查詢字段所屬字段的父類對象Class類型; * @param searchFieldName:查詢字段名稱; * @return new Object[] { searchFieldParentObject, searchField, searchFieldValue } */ private static Object[] getChildObjAttr(Object parentObj, Class<?> parentObjClass, Class<?> searchFieldParentClass, String searchFieldName) { Field[] childFields = parentObjClass.getDeclaredFields(); Field childField = null; Class<?> childFieldType = null; for (int i = 0; i < childFields.length; i++) { childField = childFields[i]; childFieldType = childField.getType(); if (!childFieldType.isMemberClass()) { if (childFieldType.equals(searchFieldParentClass)) { return getChildObjAttrDetail(parentObj, childField, searchFieldName); } } else { return getChildAttr(getFieldValue(childField, parentObj), searchFieldParentClass, searchFieldName); } } return null; } /** * 獲取 parentObj 對象中子類對象的明細屬性。 * * @param parentObj:當前對象,須要搜索查詢字段所屬的父類對象; * @param parentObjChildField:當前對象子對象,須要搜索查詢字段所屬的父類對象的子對象; * @param searchFieldName:查詢字段名稱; * @return new Object[] { searchFieldParentObject, searchField, searchFieldValue } */ private static Object[] getChildObjAttrDetail(Object parentObj, Field parentObjChildField, String searchFieldName) { parentObjChildField.setAccessible(true); Object searchFieldParentObject = null; Class<?> childClass = null; Field searchField = null; Object searchFieldValue = null; try { searchFieldParentObject = parentObjChildField.get(parentObj); childClass = searchFieldParentObject.getClass(); searchField = childClass.getDeclaredField(searchFieldName); searchField.setAccessible(true); searchFieldValue = searchField.get(searchFieldParentObject); return new Object[]{searchFieldParentObject, searchField, searchFieldValue}; } catch (IllegalArgumentException e) { Logger.error("獲取 parentObj 對象中子類對象的明細屬性異常, searchFieldName: {}, parentObj: {}, parentObjChildField: {}, " + "\n\ne: " + "{}", searchFieldName, parentObj, parentObjChildField, e); } catch (SecurityException e) { Logger.error("獲取 parentObj 對象中子類對象的明細屬性異常, searchFieldName: {}, parentObj: {}, parentObjChildField: {}, " + "\n\ne: " + "{}", searchFieldName, parentObj, parentObjChildField, e); } catch (IllegalAccessException e) { Logger.error("獲取 parentObj 對象中子類對象的明細屬性異常, searchFieldName: {}, parentObj: {}, parentObjChildField: {}, " + "\n\ne: " + "{}", searchFieldName, parentObj, parentObjChildField, e); } catch (NoSuchFieldException e) { Logger.error("獲取 parentObj 對象中子類對象的明細屬性異常, searchFieldName: {}, parentObj: {}, parentObjChildField: {}, " + "\n\ne: " + "{}", searchFieldName, parentObj, parentObjChildField, e); } return null; } /** * 獲取接口中全部實現類。 * * @param interfaceClass * @return */ public static List<Class<?>> getAllImplClasses(Class<?> interfaceClass) { if (!interfaceClass.isInterface()) { return null; } try { List<Class<?>> resultClassList = new ArrayList<Class<?>>(); // 得到接口所在的當前包名 String packageName = interfaceClass.getPackage().getName(); // 獲取接口所在處的包名下的全部實現類 List<Class<?>> allClass = getClassesByPackageName(packageName); for (int i = 0; i < allClass.size(); i++) { if (interfaceClass.isAssignableFrom(allClass.get(i))) { if (!interfaceClass.equals(allClass.get(i))) {// 自己加不進去 resultClassList.add(allClass.get(i)); } } } return resultClassList; } catch (Exception e) { Logger.error("獲取接口中全部實現類異常, interfaceClass: {}, \n\ne: {}", interfaceClass, e); return null; } } /** * 經過包名獲取當前包名下全部的類。 * * @param packageName * @return * @throws IOException * @throws ClassNotFoundException */ private static List<Class<?>> getClassesByPackageName(String packageName) throws IOException, ClassNotFoundException { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); String path = packageName.replace('.', '/'); Enumeration<URL> resources = classLoader.getResources(path); List<File> dirs = new ArrayList<File>(); while (resources.hasMoreElements()) { URL resource = resources.nextElement(); dirs.add(new File(resource.getFile())); } List<Class<?>> resultClassList = new ArrayList<Class<?>>(); for (File directory : dirs) { resultClassList.addAll(findClasses(directory, packageName)); } return resultClassList; } /** * 經過路徑以及包名,獲取全部類。 * * @param directory * @param packageName * @return * @throws ClassNotFoundException */ private static List<Class<?>> findClasses(File directory, String packageName) throws ClassNotFoundException { List<Class<?>> resultClassList = new ArrayList<Class<?>>(); if (!directory.exists()) { return resultClassList; } File[] files = directory.listFiles(); for (File file : files) { if (file.isDirectory()) { assert !file.getName().contains("."); resultClassList.addAll(findClasses(file, packageName + '.' + file.getName())); } else if (file.getName().endsWith(".class")) { resultClassList.add(Class.forName(packageName + "." + file.getName().substring(0, file.getName() .length() - 6))); } } return resultClassList; } }
package com.springms.cloud.reflect.util; import java.lang.annotation.*; /** * 成員字段註解(註解加在解析銀行返回的對象中)。 * * @author hmilyylimh * * @version 0.0.1 * * @date 2017/10/24 * */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface CustomFieldAnnotation { /** * 自定義註解名稱。 * * @return */ String customFieldName() default ""; /** * 自定義註解類型。 * * @return */ CustomFieldType customFieldType() default CustomFieldType.PRIMITIVE; /** * 標識字段是否有效。 * * @return */ boolean isEnable() default true; /** * 是否從新刷寫。 * * @return */ boolean isReWrite() default true; /** * 是不是子類屬性,是的話,則根據後面的子類所屬 Class 尋找字段屬性。 * * @return */ boolean isChild() default false; /** * 自定義註解類型 */ public static enum CustomFieldType { /** * 未知類型 */ Unknow, /** * 原生類型 */ PRIMITIVE, /** * 類成員類型 */ CLASS, /** * 數組類型 */ ARRAY, /** * 列表類型 */ LIST; public static CustomFieldType valueof(String fieldType) { if (CustomFieldType.PRIMITIVE.toString().equalsIgnoreCase(fieldType)) { return PRIMITIVE; } else if (CustomFieldType.CLASS.toString().equalsIgnoreCase(fieldType)) { return CLASS; } else if (CustomFieldType.ARRAY.toString().equalsIgnoreCase(fieldType)) { return ARRAY; } else if (CustomFieldType.LIST.toString().equalsIgnoreCase(fieldType)) { return LIST; } else { return Unknow; } } } }
package com.springms.cloud.reflect.util; import org.apache.commons.lang3.StringUtils; import org.slf4j.LoggerFactory; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; /** * 註解反射解析器。 * * @author hmilyylimh * * @version 0.0.1 * * @date 2017/10/24 * */ public class AnnotationReflectParser { private static final org.slf4j.Logger Logger = LoggerFactory.getLogger(AnnotationReflectParser.class); /** * 開始解析。 * * @param bankObject:銀行報文對象。 * @param resultObject:解析後的通用對象。 */ public static boolean start(Object bankObject, Object resultObject) { try { convert(bankObject, resultObject); return true; } catch (Exception e) { Logger.error("開始解析出現最外層異常,bankObject: {}, resultObject: {}", bankObject, resultObject); return false; } } /** * 循環嵌套解析,該方法會被循環調用屢次。 * * @param bankObject:銀行報文對象。 * @param resultObject:解析後的通用對象。 */ private static void convert(Object bankObject, Object resultObject) { if (bankObject == null) { Logger.error("循環嵌套解析,傳入 bankObject 爲空, bankObject: {}, resultObject: {}", bankObject, resultObject); throw new RuntimeException("循環嵌套解析,傳入 bankObject 爲空"); } if (resultObject == null) { Logger.error("循環嵌套解析,傳入 resultObject 爲空, bankObject: {}, resultObject: {}", bankObject, resultObject); throw new RuntimeException("循環嵌套解析,傳入 resultObject 爲空"); } Class<?> bankObjClass = bankObject.getClass(); List<Field> bankFields = ReflectionUtil.getDeclaredSuperFields(bankObjClass); if (bankFields == null || bankFields.isEmpty()) { Logger.error("循環嵌套解析,bankObject 對象內沒有 Field 屬性字段, bankObject: {}, resultObject: {}", bankObject, resultObject); return; } CustomFieldAnnotation customFieldAnnotation = null; CustomFieldAnnotation.CustomFieldType customFieldType = null; for (Field bankField : bankFields) { customFieldAnnotation = bankField.getAnnotation(CustomFieldAnnotation.class); // 過濾沒有註解的字段 if (customFieldAnnotation == null) { // Logger.error("循環嵌套解析,過濾沒有註解的字段, bankField: {}, bankObject: {}, resultObject: {}", bankField, bankObject, resultObject); continue; } // 過濾已經禁用的字段 if (!customFieldAnnotation.isEnable()) { Logger.error("循環嵌套解析,過濾已經禁用的字段, bankField: {}, bankObject: {}, resultObject: {}", bankField, bankObject, resultObject); continue; } // 過濾沒有定義類型的字段 customFieldType = customFieldAnnotation.customFieldType(); if (customFieldType == null || customFieldType == CustomFieldAnnotation.CustomFieldType.Unknow) { Logger.error("循環嵌套解析,過濾沒有定義類型的字段, bankField: {}, bankObject: {}, resultObject: {}", bankField, bankObject, resultObject); continue; } // 針對不一樣類型走不一樣分支處理 switch (customFieldType) { case PRIMITIVE: { setPrimitiveType(bankField, bankObject, customFieldAnnotation, resultObject); break; } case CLASS: { setClassType(bankField, bankObject, customFieldAnnotation, resultObject); break; } case ARRAY: { setArrayType(bankField, bankObject, customFieldAnnotation, resultObject); break; } case LIST: { setListType(bankField, bankObject, customFieldAnnotation, resultObject); break; } case Unknow: { String msg = String.format("循環嵌套解析, 走進了沒有邏輯處理的分支類型, customFieldName: %s, bankFieldName: %s", customFieldAnnotation.customFieldName(), bankField.getName()); Logger.error(msg); throw new RuntimeException(msg); } } } } /** * 設置基本類型字段。 * * @param bankField * @param bankFieldParentObj * @param customFieldAnnotation * @param resultObject */ private static void setPrimitiveType(Field bankField, Object bankFieldParentObj, CustomFieldAnnotation customFieldAnnotation, Object resultObject) { try { String customFieldName = customFieldAnnotation.customFieldName(); Object bankFieldValue = ReflectionUtil.getFieldValue(bankField, bankFieldParentObj); Object[] fieldMapping = AnnotationMapping.getGeneralFieldMapping().get(customFieldName); if (fieldMapping == null) { String msg = String.format("設置基本類型字段, 沒有設置通用字段映射關係, customFieldName: %s, bankFieldName: %s", customFieldName, bankField.getName()); Logger.error(msg); throw new RuntimeException(msg); } String commonMappingFieldName = (String) fieldMapping[0]; if (StringUtils.isEmpty(commonMappingFieldName)) { String msg = String.format("設置基本類型字段, 通用對象中的屬性字段爲空, customFieldName: %s, bankFieldName: %s", customFieldName, bankField.getName()); Logger.error(msg); throw new RuntimeException(msg); } // 獲取 resultObject 結果對象中 commonMappingFieldName 字段對象 Field // 從 resultObject 當前對象找,以及從 resultObject 父類找 commonMappingFieldName 屬性字段 Field commonMappingField = ReflectionUtil.getDeclaredField(resultObject, commonMappingFieldName); Object fieldParentObj = resultObject; if (customFieldAnnotation.isChild() || commonMappingField == null) { // 若是找不到的話,那麼則嘗試從 resultObject 對象的子對象遞歸子對象找 commonMappingFieldName 屬性字段 Class<?> commonMappingFieldSuperClass = (Class<?>) fieldMapping[1]; Object[] childAttr = ReflectionUtil.getChildAttr(resultObject, commonMappingFieldSuperClass, commonMappingFieldName); if (childAttr == null) { String msg = String.format("設置基本類型字段, 在通用對象的子類中沒有搜索到通用屬性字段, customFieldName: %s, bankFieldName: %s, " + "commonMappingFieldName: %s", customFieldName, bankField.getName(), commonMappingFieldName); Logger.error(msg); throw new RuntimeException(msg); } fieldParentObj = childAttr[0]; commonMappingField = (Field) childAttr[1]; } // 給結果對象 resultObject 賦值,類型對等則直接賦值 if (customFieldAnnotation.isReWrite()) { ReflectionUtil.setFieldValue(commonMappingField, fieldParentObj, bankFieldValue); } else if (commonMappingField.getType() == bankFieldValue.getClass()) { ReflectionUtil.setFieldValue(commonMappingField, fieldParentObj, bankFieldValue); } // 類型不對等的話,則記錄錯誤日誌 else { Logger.error("設置基本類型字段, 類型不對等的話, 銀行字段名稱: {}, 通用對象字段名稱: {}, bankFieldParentObj: {}, customFieldAnnotation: {}, " + "resultObject: {}", bankField.getName(), customFieldAnnotation.customFieldName(), bankFieldParentObj, customFieldAnnotation, resultObject); } } catch (Exception e) { Logger.error("設置基本類型字段異常, 銀行字段名稱: {}, 通用對象字段名稱: {}, bankFieldParentObj: {}, customFieldAnnotation: {}, " + "resultObject: {}, \n\ne: " + "{}", bankField.getName(), customFieldAnnotation.customFieldName(), bankFieldParentObj, customFieldAnnotation, resultObject, e); throw new RuntimeException("設置基本類型字段異常"); } } /** * 設置類成員類型字段。 * * @param bankField * @param bankFieldParentObj * @param customFieldAnnotation * @param resultObject */ private static void setClassType(Field bankField, Object bankFieldParentObj, CustomFieldAnnotation customFieldAnnotation, Object resultObject) { try { String customFieldName = customFieldAnnotation.customFieldName(); Object bankFieldValue = ReflectionUtil.getFieldValue(bankField, bankFieldParentObj); if (bankFieldValue == null) { Logger.error("設置類成員類型字段,解析銀行對象中 {} 屬性字段值爲空。", bankField.getName()); return; } Class<?> bankFieldObjClass = bankFieldValue.getClass(); Field[] bankFieldObjFields = bankFieldObjClass.getDeclaredFields(); if (bankFieldObjFields == null || bankFieldObjFields.length == 0) { Logger.error("設置類成員類型字段,bankField 對象內沒有 Field 屬性字段, bankFieldName: {}, bankFieldParentObj: {}, " + "customFieldAnnotation: {}, resultObject: {}, ", bankField.getName(), bankFieldParentObj, customFieldAnnotation, resultObject); return; } // resultObject 該對象有數據,那麼就得在 resultObject 中實例化對應的對象 Object[] fieldMapping = AnnotationMapping.getGeneralFieldMapping().get(customFieldName); if (fieldMapping == null) { String msg = String.format("設置類成員類型字段, 沒有設置通用字段映射關係, customFieldName: %s, bankFieldName: %s", customFieldName, bankField.getName()); Logger.error(msg); throw new RuntimeException(msg); } String commonMappingFieldName = (String) fieldMapping[0]; if (StringUtils.isEmpty(commonMappingFieldName)) { String msg = String.format("設置類成員類型字段, 通用對象中的屬性字段爲空, customFieldName: %s, bankFieldName: %s", customFieldName, bankField.getName()); Logger.error(msg); throw new RuntimeException(msg); } // 從 resultObject 當前對象找,以及從 resultObject 父類找 commonMappingFieldName 屬性字段 Field commonMappingField = ReflectionUtil.getDeclaredField(resultObject, commonMappingFieldName); Object fieldParentObj = resultObject; if (commonMappingField == null) { // 若是找不到的話,那麼則嘗試從 resultObject 對象的子對象遞歸子對象找 commonMappingFieldName 屬性字段 Class<?> commonMappingFieldSuperClass = (Class<?>) fieldMapping[1]; Object[] childAttr = ReflectionUtil.getChildAttr(resultObject, commonMappingFieldSuperClass, commonMappingFieldName); if (childAttr == null) { String msg = String.format("設置類成員類型字段, 在通用對象的子類中沒有搜索到通用屬性字段, customFieldName: %s, bankFieldName: %s, " + "commonMappingFieldName: %s", customFieldName, bankField.getName(), commonMappingFieldName); Logger.error(msg); throw new RuntimeException(msg); } fieldParentObj = childAttr[0]; commonMappingField = (Field) childAttr[1]; } // 獲取 resultObject 結果對象中 Field 字段的值 if (ReflectionUtil.getFieldValue(commonMappingField, fieldParentObj) == null) { Object newInstance = commonMappingField.getType().newInstance(); ReflectionUtil.setFieldValue(commonMappingField, resultObject, newInstance); } convert(bankFieldValue, resultObject); } catch (Exception e) { Logger.error("設置類成員類型字段異常, bankField: {}, bankFieldParentObj: {}, customFieldAnnotation: {}, " + "resultObject: {}, \n\ne: " + "{}", bankField, bankFieldParentObj, customFieldAnnotation, resultObject, e); throw new RuntimeException("設置類成員類型字段異常"); } } /** * 設置數組類型字段。 * * @param bankField * @param bankFieldParentObj * @param customFieldAnnotation * @param resultObject */ private static void setArrayType(Field bankField, Object bankFieldParentObj, CustomFieldAnnotation customFieldAnnotation, Object resultObject) { try { String customFieldName = customFieldAnnotation.customFieldName(); Object bankFieldValue = ReflectionUtil.getFieldValue(bankField, bankFieldParentObj); if (bankFieldValue == null) { Logger.error("設置數組類型字段,解析銀行對象中 {} 屬性字段值爲空。", bankField.getName()); return; } int length = Array.getLength(bankFieldValue); if (length <= 0) { String msg = String.format("設置數組類型字段, 銀行數組長度爲空, customFieldName: %s, bankFieldName: %s", customFieldName, bankField.getName()); Logger.error(msg); return; } // resultObject 該對象有數據,那麼就得在 resultObject 中實例化對應的對象 Object[] fieldMapping = AnnotationMapping.getGeneralFieldMapping().get(customFieldName); if (fieldMapping == null) { String msg = String.format("設置數組類型字段, 沒有設置通用字段映射關係, customFieldName: %s, bankFieldName: %s", customFieldName, bankField.getName()); Logger.error(msg); throw new RuntimeException(msg); } String commonMappingFieldName = (String) fieldMapping[0]; if (StringUtils.isEmpty(commonMappingFieldName)) { String msg = String.format("設置數組類型字段, 通用對象中的屬性字段爲空, customFieldName: %s, bankFieldName: %s", customFieldName, bankField.getName()); Logger.error(msg); throw new RuntimeException(msg); } // 從 resultObject 當前對象找,以及從 resultObject 父類找 commonMappingFieldName 屬性字段 Field commonMappingField = ReflectionUtil.getDeclaredField(resultObject, commonMappingFieldName); Object fieldParentObj = resultObject; if (commonMappingField == null) { // 若是找不到的話,那麼則嘗試從 resultObject 對象的子對象遞歸子對象找 commonMappingFieldName 屬性字段 Class<?> commonMappingFieldSuperClass = (Class<?>) fieldMapping[1]; Object[] childAttr = ReflectionUtil.getChildAttr(resultObject, commonMappingFieldSuperClass, commonMappingFieldName); if (childAttr == null) { String msg = String.format("設置數組類型字段, 在通用對象的子類中沒有搜索到通用屬性字段, customFieldName: %s, bankFieldName: %s, " + "commonMappingFieldName: %s", customFieldName, bankField.getName(), commonMappingFieldName); Logger.error(msg); throw new RuntimeException(msg); } fieldParentObj = childAttr[0]; commonMappingField = (Field) childAttr[1]; } // 獲取 resultObject 結果對象中 Field 字段的值 if (ReflectionUtil.getFieldValue(commonMappingField, fieldParentObj) == null) { Class<?> elementType = commonMappingField.getType(); String elementTypeName = elementType.getName(); int startIndex = elementTypeName.indexOf("com"); int endIndex = elementTypeName.lastIndexOf(";"); String innerClassName = elementTypeName.substring(startIndex, endIndex); Class<?> innerClass = Class.forName(innerClassName); // 實例化數組 Object newInstance = Array.newInstance(innerClass, length); // 數組賦值空對象 Object[] arrays = (Object[]) newInstance; Object[] bankFieldValueArrays = (Object[]) bankFieldValue; for (int i = 0; i < length; i++) { arrays[i] = innerClass.newInstance(); } // 將空數組賦值到 resultObject 結果對象中 ReflectionUtil.setFieldValue(commonMappingField, fieldParentObj, newInstance); // 循環解析 bankFieldValueArrays 的值放到結果對象中對應的索引位置中 for (int i = 0; i < length; i++) { Object itemResultObject = arrays[i]; convert(bankFieldValueArrays[i], itemResultObject); } } } catch (Exception e) { Logger.error("設置數組類型字段異常, bankField: {}, bankFieldParentObj: {}, customFieldAnnotation: {}, " + "resultObject: {}, \n\ne: " + "{}", bankField, bankFieldParentObj, customFieldAnnotation, resultObject, e); throw new RuntimeException("設置數組類型字段異常"); } } /** * 設置列表類型字段。 * * @param bankField * @param bankFieldParentObj * @param customFieldAnnotation * @param resultObject */ private static void setListType(Field bankField, Object bankFieldParentObj, CustomFieldAnnotation customFieldAnnotation, Object resultObject) { try { String customFieldName = customFieldAnnotation.customFieldName(); Object bankFieldValue = ReflectionUtil.getFieldValue(bankField, bankFieldParentObj); if (bankFieldValue == null) { Logger.error("設置列表類型字段,解析銀行對象中 {} 屬性字段值爲空。", bankField.getName()); return; } List bankFieldValueList = (List) bankFieldValue; int size = bankFieldValueList.size(); if (size <= 0) { String msg = String.format("設置列表類型字段, 銀行列表長度爲空, customFieldName: %s, bankFieldName: %s", customFieldName, bankField.getName()); Logger.error(msg); return; } // resultObject 該對象有數據,那麼就得在 resultObject 中實例化對應的對象 Object[] fieldMapping = AnnotationMapping.getGeneralFieldMapping().get(customFieldName); if (fieldMapping == null) { String msg = String.format("設置列表類型字段, 沒有設置通用字段映射關係, customFieldName: %s, bankFieldName: %s", customFieldName, bankField.getName()); Logger.error(msg); throw new RuntimeException(msg); } String commonMappingFieldName = (String) fieldMapping[0]; if (StringUtils.isEmpty(commonMappingFieldName)) { String msg = String.format("設置列表類型字段, 通用對象中的屬性字段爲空, customFieldName: %s, bankFieldName: %s", customFieldName, bankField.getName()); Logger.error(msg); throw new RuntimeException(msg); } // 從 resultObject 當前對象找,以及從 resultObject 父類找 commonMappingFieldName 屬性字段 Field commonMappingField = ReflectionUtil.getDeclaredField(resultObject, commonMappingFieldName); Object fieldParentObj = resultObject; if (commonMappingField == null) { // 若是找不到的話,那麼則嘗試從 resultObject 對象的子對象遞歸子對象找 commonMappingFieldName 屬性字段 Class<?> commonMappingFieldSuperClass = (Class<?>) fieldMapping[1]; Object[] childAttr = ReflectionUtil.getChildAttr(resultObject, commonMappingFieldSuperClass, commonMappingFieldName); if (childAttr == null) { String msg = String.format("設置列表類型字段, 在通用對象的子類中沒有搜索到通用屬性字段, customFieldName: %s, bankFieldName: %s, " + "commonMappingFieldName: %s", customFieldName, bankField.getName(), commonMappingFieldName); Logger.error(msg); throw new RuntimeException(msg); } fieldParentObj = childAttr[0]; commonMappingField = (Field) childAttr[1]; } Type genericType = commonMappingField.getGenericType(); if(!(genericType instanceof ParameterizedType)){ String msg = String.format("設置列表類型字段, 通用對象中的屬性字段類型設置有誤,設置的不是列表類型, customFieldName: %s, bankFieldName: %s", customFieldName, bankField.getName()); Logger.error(msg); return; } // 獲取 resultObject 結果對象中 Field 字段的值 if (ReflectionUtil.getFieldValue(commonMappingField, fieldParentObj) == null) { ParameterizedType parameterizedType = (ParameterizedType)genericType; Class<?> innerClass = (Class) parameterizedType.getActualTypeArguments()[0];//獲得對象list中實例的類型 // 實例化數組 List newInstance = new ArrayList(); // 數組賦值空對象 for (int i = 0; i < size; i++) { newInstance.add(innerClass.newInstance()); } // 將空數組賦值到 resultObject 結果對象中 ReflectionUtil.setFieldValue(commonMappingField, fieldParentObj, newInstance); // 循環解析 bankFieldValueArrays 的值放到結果對象中對應的索引位置中 for (int i = 0; i < size; i++) { Object itemResultObject = newInstance.get(i); convert(bankFieldValueList.get(i), itemResultObject); } } } catch (Exception e) { Logger.error("設置列表類型字段異常, bankField: {}, bankFieldParentObj: {}, customFieldAnnotation: {}, " + "resultObject: {}, \n\ne: " + "{}", bankField, bankFieldParentObj, customFieldAnnotation, resultObject, e); throw new RuntimeException("設置列表類型字段異常"); } } }
package com.springms.cloud.reflect; import com.springms.cloud.reflect.util.AnnotationReflectParser; import com.springms.cloud.reflect.util.xml.BeanXml; /** * 測試類。 * * @author hmilyylimh * * @version 0.0.1 * * @date 2017/10/24 * */ public class TestReflectDemo { public static void main(String[] args) { try { String xmlData = getXml(); Class<?> beanClass = getBeanClassPath(); Object respBankDTO = BeanXml.xml2Bean(xmlData, beanClass); ResultDTO resultObject = new ResultDTO(); ResultDTO.Record record = new ResultDTO.Record(); resultObject.setRecord(record); boolean finished = AnnotationReflectParser.start(respBankDTO, resultObject); System.out.println("finished: " + finished); System.out.println("====================================="); } catch (Exception e) { e.printStackTrace(); } } /** * 這裏能夠經過路徑反射獲得 Class 類,若是你的類有規律的話,那完成能夠在這個地方經過設定規則出來獲得類名路徑。 * * 那麼我這裏呢,就直接拿個例子來試試而已。 * * @return */ private static Class<?> getBeanClassPath() { String className = "com.springms.cloud.reflect.BankDTO"; return getRespBeanClass(className); } private static String getXml() { String recvContent = "<?xml version='1.0' encoding='GB2312'?>\n" + "<packet>\n" + "<head>\n" + "<transCode>4469</transCode> \n" + "<signFlag>0</signFlag> \n" + "<packetID>1234567890</packetID> \n" + "<timeStamp>2004-07-28 16:14:29</timeStamp> \n" + "<returnCode>AAAAAAA</returnCode> \n" + "</head>\n" + "<body>\n" + "<acctNo>246333388999</acctNo>\n" + "<acctName>張三</acctName>\n" + "<acctBalance>199098777.97</acctBalance>\n" + "<subTotBalance>199098777.97</subTotBalance>\n" + "<lists name=\"LoopResult\">\n" + "<list>\n" + "<subAcctNo>1234567890000000</subAcctNo>\n" + "<subAcctBalance>234.56</subAcctBalance>\n" + "<subAcctName>帳戶名稱甲</subAcctName>\n" + "</list>\n" + "</lists>\n" + "</body>\n" + "</packet>"; return recvContent; } /** * 獲取響應類名的 Class 對象。 * * @return */ private static Class<?> getRespBeanClass(String className) { Class<?> respClass = null; try { respClass = Class.forName(className); return respClass; } catch (ClassNotFoundException e) { throw new RuntimeException(className + " 該響應類路徑不存在", e); } } }
一、雖然這樣寫能夠偷懶了,也能夠招非開發人員直接上手擼代碼直接開發功能模塊,可是不方便的地方就是得發版升級; 二、後期想法,咱們不是有 "Java運行時動態加載類" 這麼一說麼?後期準備將這一套代碼放在某個目錄上傳,或者直接放到數據庫存儲,而後動態加載執行對應功能; 三、想法雖然不錯,路漫漫其修遠兮,慢慢努力吧,順便祝各位猿猿們節日快樂;
https://gitee.com/ylimhhmily/SpringCloudTutorial.gitjava
SpringCloudTutorial交流QQ羣: 235322432git
SpringCloudTutorial交流微信羣: 微信溝通羣二維碼圖片連接spring
歡迎關注,您的確定是對我最大的支持!!!數據庫