Reflect 通过反射获取自定义注解值给另外一个对象赋值
-
一、大致介绍
1、今天刚完成这么一个功能模块,需求场景是这样的,我们需要对接许多银行的接口,我们解析银行XML报文后,根据每个银行每个接口我们会解析得到很多BankDTO; 2、然后我们需要在BankDTO挑出一些必要的字段放到另外一个 ResultDTO 中去,然后将 ResultDTO 的数据入库处理; 3、而且最关键的是,每个银行的字段五花八门,我们根本没办法统一字段,最初的办法我们是对每个 BankDTO 写了一个转换类转成 ResultDTO; 4、但是随着接入的银行越来越多了,开发效率也就慢慢的降下来了,然而我就在思考如何优化这个字段转换来转换去的笨重方法; 5、经过辗转反侧的思考,最终自己定义一个注解类,然后将这些注解安插在BankDTO上,而我们需要做的事情就是反射获取注解值然后给ResultDTO赋值即可; 6、原理就是这么简单,这样写好之后,银行一多,开发人员不够,我们找些不会开发的人员只要告诉他们如何写 BankDTO 对象即可,如何映射字段值即可,最后提交代码就搞定了; 7、而我在这里主要将一些类贴出来仅供大家参考,如果这种思路在大家工作中用得着的话,相信稍微复用我这思路,功能很快就能水到渠成;
二、实现步骤
2.1 反射工具类,参考网上代码做了稍微调整,整理成符合自己业务逻辑的公用工具类
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: {},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(),获取对象的 DeclaredMethod 异常,methodName: {},parameterTypes: {},methodName,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: {},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 字段的值异常,newValueObj: {},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: " + "{}",searchFieldName,parentObj,e); } catch (IllegalAccessException e) { Logger.error("获取当前对象中子对象的属性异常,e); } return result; } /** * 获取 parentObj 对象中子类对象的属性。 * * @param parentObj:当前对象,需要搜索查询字段所属的父类对象; * @param parentObjClass:当前对象类名称类型,需要搜索查询字段所属的父类类名称类型; * @param searchFieldParentClass:查询字段所属字段的父类对象Class类型; * @param searchFieldName:查询字段名称; * @return new Object[] { searchFieldParentObject,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),searchFieldName); } } return null; } /** * 获取 parentObj 对象中子类对象的明细属性。 * * @param parentObj:当前对象,需要搜索查询字段所属的父类对象; * @param parentObjChildField:当前对象子对象,需要搜索查询字段所属的父类对象的子对象; * @param searchFieldName:查询字段名称; * @return new Object[] { searchFieldParentObject,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,searchFieldValue}; } catch (IllegalArgumentException e) { Logger.error("获取 parentObj 对象中子类对象的明细属性异常,parentObjChildField: {}," + "\n\ne: " + "{}",parentObjChildField,e); } catch (SecurityException e) { Logger.error("获取 parentObj 对象中子类对象的明细属性异常,e); } catch (IllegalAccessException e) { Logger.error("获取 parentObj 对象中子类对象的明细属性异常,e); } catch (NoSuchFieldException e) { Logger.error("获取 parentObj 对象中子类对象的明细属性异常,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: {},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; } }
2.2 自定义注解类,主要用来安插在银行响应类BankDTO身上的;
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; } } } }
2.3 反射获取注解值并给 ResultDTO 赋值的解析器类,非常非常重要的类
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); throw new RuntimeException("循环嵌套解析,传入 bankObject 为空"); } if (resultObject == null) { Logger.error("循环嵌套解析,传入 resultObject 为空,resultObject); throw new RuntimeException("循环嵌套解析,传入 resultObject 为空"); } Class<?> bankObjClass = bankObject.getClass(); List<Field> bankFields = ReflectionUtil.getDeclaredSuperFields(bankObjClass); if (bankFields == null || bankFields.isEmpty()) { Logger.error("循环嵌套解析,bankObject 对象内没有 Field 属性字段,resultObject); return; } CustomFieldAnnotation customFieldAnnotation = null; CustomFieldAnnotation.CustomFieldType customFieldType = null; for (Field bankField : bankFields) { customFieldAnnotation = bankField.getAnnotation(CustomFieldAnnotation.class); // 过滤没有注解的字段 if (customFieldAnnotation == null) { // Logger.error("循环嵌套解析,过滤没有注解的字段,bankField: {},bankField,resultObject); continue; } // 过滤已经禁用的字段 if (!customFieldAnnotation.isEnable()) { Logger.error("循环嵌套解析,过滤已经禁用的字段,resultObject); continue; } // 过滤没有定义类型的字段 customFieldType = customFieldAnnotation.customFieldType(); if (customFieldType == null || customFieldType == CustomFieldAnnotation.CustomFieldType.Unknow) { Logger.error("循环嵌套解析,过滤没有定义类型的字段,resultObject); continue; } // 针对不同类型走不同分支处理 switch (customFieldType) { case PRIMITIVE: { setPrimitiveType(bankField,customFieldAnnotation,resultObject); break; } case CLASS: { setClassType(bankField,resultObject); break; } case ARRAY: { setArrayType(bankField,resultObject); break; } case LIST: { setListType(bankField,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,bankField.getName()); Logger.error(msg); throw new RuntimeException(msg); } String commonMappingFieldName = (String) fieldMapping[0]; if (StringUtils.isEmpty(commonMappingFieldName)) { String msg = String.format("设置基本类型字段,通用对象中的属性字段为空,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("设置基本类型字段,在通用对象的子类中没有搜索到通用属性字段,bankFieldName: %s," + "commonMappingFieldName: %s",bankField.getName(),commonMappingFieldName); Logger.error(msg); throw new RuntimeException(msg); } fieldParentObj = childAttr[0]; commonMappingField = (Field) childAttr[1]; } // 给结果对象 resultObject 赋值,类型对等则直接赋值 if (customFieldAnnotation.isReWrite()) { ReflectionUtil.setFieldValue(commonMappingField,bankFieldValue); } else if (commonMappingField.getType() == bankFieldValue.getClass()) { ReflectionUtil.setFieldValue(commonMappingField,bankFieldValue); } // 类型不对等的话,则记录错误日志 else { Logger.error("设置基本类型字段,类型不对等的话,银行字段名称: {},通用对象字段名称: {},bankFieldParentObj: {},customFieldAnnotation: {}," + "resultObject: {}",bankFieldParentObj,resultObject); } } catch (Exception e) { Logger.error("设置基本类型字段异常," + "resultObject: {},\n\ne: " + "{}",resultObject,e); throw new RuntimeException("设置基本类型字段异常"); } } /** * 设置类成员类型字段。 * * @param bankField * @param bankFieldParentObj * @param customFieldAnnotation * @param resultObject */ private static void setClassType(Field 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: {}," + "customFieldAnnotation: {},resultObject: {},",resultObject); return; } // resultObject 该对象有数据,那么就得在 resultObject 中实例化对应的对象 Object[] fieldMapping = AnnotationMapping.getGeneralFieldMapping().get(customFieldName); if (fieldMapping == null) { String msg = String.format("设置类成员类型字段,bankField.getName()); Logger.error(msg); throw new RuntimeException(msg); } String commonMappingFieldName = (String) fieldMapping[0]; if (StringUtils.isEmpty(commonMappingFieldName)) { String msg = String.format("设置类成员类型字段,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,commonMappingFieldName); if (childAttr == null) { String msg = String.format("设置类成员类型字段,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,newInstance); } convert(bankFieldValue,resultObject); } catch (Exception e) { Logger.error("设置类成员类型字段异常,e); throw new RuntimeException("设置类成员类型字段异常"); } } /** * 设置数组类型字段。 * * @param bankField * @param bankFieldParentObj * @param customFieldAnnotation * @param resultObject */ private static void setArrayType(Field bankField,bankFieldParentObj); if (bankFieldValue == null) { Logger.error("设置数组类型字段,解析银行对象中 {} 属性字段值为空。",bankField.getName()); return; } int length = Array.getLength(bankFieldValue); if (length <= 0) { String msg = String.format("设置数组类型字段,银行数组长度为空,bankField.getName()); Logger.error(msg); return; } // resultObject 该对象有数据,那么就得在 resultObject 中实例化对应的对象 Object[] fieldMapping = AnnotationMapping.getGeneralFieldMapping().get(customFieldName); if (fieldMapping == null) { String msg = String.format("设置数组类型字段,bankField.getName()); Logger.error(msg); throw new RuntimeException(msg); } String commonMappingFieldName = (String) fieldMapping[0]; if (StringUtils.isEmpty(commonMappingFieldName)) { String msg = String.format("设置数组类型字段,commonMappingFieldName); if (childAttr == null) { String msg = String.format("设置数组类型字段,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,newInstance); // 循环解析 bankFieldValueArrays 的值放到结果对象中对应的索引位置中 for (int i = 0; i < length; i++) { Object itemResultObject = arrays[i]; convert(bankFieldValueArrays[i],itemResultObject); } } } catch (Exception e) { Logger.error("设置数组类型字段异常,e); throw new RuntimeException("设置数组类型字段异常"); } } /** * 设置列表类型字段。 * * @param bankField * @param bankFieldParentObj * @param customFieldAnnotation * @param resultObject */ private static void setListType(Field 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("设置列表类型字段,银行列表长度为空,bankField.getName()); Logger.error(msg); return; } // resultObject 该对象有数据,那么就得在 resultObject 中实例化对应的对象 Object[] fieldMapping = AnnotationMapping.getGeneralFieldMapping().get(customFieldName); if (fieldMapping == null) { String msg = String.format("设置列表类型字段,bankField.getName()); Logger.error(msg); throw new RuntimeException(msg); } String commonMappingFieldName = (String) fieldMapping[0]; if (StringUtils.isEmpty(commonMappingFieldName)) { String msg = String.format("设置列表类型字段,commonMappingFieldName); if (childAttr == null) { String msg = String.format("设置列表类型字段,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("设置列表类型字段,通用对象中的属性字段类型设置有误,设置的不是列表类型,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,newInstance); // 循环解析 bankFieldValueArrays 的值放到结果对象中对应的索引位置中 for (int i = 0; i < size; i++) { Object itemResultObject = newInstance.get(i); convert(bankFieldValueList.get(i),itemResultObject); } } } catch (Exception e) { Logger.error("设置列表类型字段异常,e); throw new RuntimeException("设置列表类型字段异常"); } } }
2.4 测试代码,如何调用起我们写的这套功能
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); } } }
2.5 总结
1、虽然这样写可以偷懒了,也可以招非开发人员直接上手撸代码直接开发功能模块,但是不方便的地方就是得发版升级; 2、后期想法,我们不是有 "Java运行时动态加载类" 这么一说么?后期准备将这一套代码放在某个目录上传,或者直接放到数据库存储,然后动态加载执行对应功能; 3、想法虽然不错,路漫漫其修远兮,慢慢努力吧,顺便祝各位猿猿们节日快乐;
三、下载地址
https://git.oschina.net/ylimhhmily/SpringCloudTutorial.git
SpringCloudTutorial交流QQ群: 235322432
SpringCloudTutorial交流微信群: 微信沟通群二维码图片链接
欢迎关注,您的肯定是对我最大的支持!!!
原文链接:/xml/293671.html