切面编程中有一个场景,req中肯定有projectIds字段有的是List<Long> projectIds有的是Set<Long> projectIds,需要先获取原来projectIds值,根据逻辑处理后修改projectIds, 如果原来是List<Long>类型肯定在修改赋值时是List<Long>类型否则对应Set<Long>类型。且req集成了父类,父类又集成了父类,projectId不一定在哪个父类中。传统的映射获取值直接报错,参考下面工具类循环去父类中查找projectIds字段后获取再修改。
含多级父类时指定字段不一定在子级或哪个父级时,可循环映射获取到指定字段值和类型。封装了工具类(ReflectionUtils.java)如下:
import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Type; public class ReflectionUtils { /** * 可获取父类和子类的所有方法 * @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) { e.printStackTrace(); } } return null; } public static Field getDeclaredField(Object object, String methodName){ Field fieldRes = null; Class<?> clazz = object.getClass(); while (clazz != null && !Object.class.equals(clazz)) { Field field = getDeclaredFieldRecursively(clazz, methodName); // 要查询的属性名称 if (field == null) { // System.out.println("未找到该属性!"); break; } else { Type genericType = field.getGenericType(); // 获取属性的泛型类型 if(methodName.equals(field.getName())){ fieldRes = field; break; } // System.out.println("属性名称:" + field.getName()); // System.out.println("属性泛型类型:" + genericType); clazz = clazz.getSuperclass(); // 递归调用父类 } } return fieldRes; } private static Field getDeclaredFieldRecursively(Class<?> clazz, String propertyName) { try { return clazz.getDeclaredField(propertyName); } catch (NoSuchFieldException e) { if (clazz.getSuperclass() != null) { return getDeclaredFieldRecursively(clazz.getSuperclass(), propertyName); } else { throw new RuntimeException("无法找到属性:" + propertyName); } } } }
比如获取 projectIds字段是List<Long>还是 Set<Long>类型,然后根据类型赋值后修改值