1 import org.apache.commons.lang3.StringUtils; 2 import org.apache.commons.lang3.Validate; 3 import org.apache.poi.ss.formula.functions.T; 4 import org.slf4j.Logger; 5 import org.slf4j.LoggerFactory; 6 7 import java.lang.reflect.*; 8 import java.util.HashMap; 9 import java.util.Map; 10 11 /** 12 * ClassName: Reflections 13 * @Description: 反射工具类.提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class,被AOP过的真实类等工具函数. 14 * @author 15 * @date 2015年9月9日 下午1:02:26 16 */ 17 public class Reflections { 18 private static final String SETTER_PREFIX = "set"; 19 20 private static final String GETTER_PREFIX = "get"; 21 22 private static final String CGLIB_CLASS_SEPARATOR = "$$"; 23 24 private static Logger logger = LoggerFactory.getLogger(Reflections.class); 25 26 /** 27 * @Description: 调用Getter方法. 28 * @param obj 29 * @param propertyName 30 * @return 31 * @return Object 32 * @throws 33 * @author feifei.liu 34 * @date 2015年9月25日 下午7:55:46 35 */ 36 public static Object invokeGetter(Object obj, String propertyName) { 37 String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(propertyName); 38 return invokeMethod(obj, getterMethodName, new Class[] {}, new Object[] {}); 39 } 40 41 /** 42 * @Description: 调用Setter方法, 仅匹配方法名。 43 * @param obj 44 * @param propertyName 45 * @param value 46 * @return void 47 * @throws 48 * @author feifei.liu 49 * @date 2015年9月25日 下午7:55:59 50 */ 51 public static void invokeSetter(Object obj, String propertyName, Object value) { 52 String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(propertyName); 53 invokeMethodByName(obj, setterMethodName, new Object[] { value }); 54 } 55 56 /** 57 * @Description: 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数. 58 * @param obj 59 * @param fieldName 60 * @return 61 * @return Object 62 * @throws 63 * @author feifei.liu 64 * @date 2015年9月25日 下午7:56:13 65 */ 66 public static Object getFieldValue(final Object obj, final String fieldName) { 67 Field field = getAccessibleField(obj, fieldName); 68 69 if (field == null) { 70 throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + obj + "]"); 71 } 72 73 Object result = null; 74 try { 75 result = field.get(obj); 76 } catch (IllegalAccessException e) { 77 logger.error("不可能抛出的异常{}", e.getMessage()); 78 } 79 return result; 80 } 81 82 /** 83 * @Description: 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数. 84 * @param obj 85 * @param fieldName 86 * @param value 87 * @return void 88 * @throws 89 * @author feifei.liu 90 * @date 2015年9月25日 下午7:56:26 91 */ 92 public static void setFieldValue(final Object obj, final String fieldName, final Object value) { 93 Field field = getAccessibleField(obj, fieldName); 94 95 if (field == null) { 96 throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + obj + "]"); 97 } 98 99 try {100 /*if("false".equals(value) || "true".equals(value)){101 Boolean b = new Boolean(value.toString());102 boolean b1 = b.booleanValue();103 field.set(obj, b1);104 }else{105 field.set(obj, value);106 }*/107 field.set(obj, value);108 } catch (IllegalAccessException e) {109 logger.error("不可能抛出的异常:{}", e.getMessage());110 }111 }112 113 /**114 * @Description: 直接调用对象方法, 无视private/protected修饰符.115 * 用于一次性调用的情况,否则应使用getAccessibleMethod()函数获得Method后反复调用. 同时匹配方法名+参数类型.116 * @param obj117 * @param methodName118 * @param parameterTypes119 * @param args120 * @return 121 * @return Object 122 * @throws123 * @author feifei.liu124 * @date 2015年9月25日 下午7:56:33125 */126 public static Object invokeMethod(final Object obj, final String methodName, final Class [] parameterTypes,127 final Object[] args) {128 Method method = getAccessibleMethod(obj, methodName, parameterTypes);129 if (method == null) {130 throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]");131 }132 133 try {134 return method.invoke(obj, args);135 } catch (Exception e) {136 throw convertReflectionExceptionToUnchecked(e);137 }138 }139 140 /**141 * @Description: 直接调用对象方法, 无视private/protected修饰符,142 * 用于一次性调用的情况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用.143 * 只匹配函数名,如果有多个同名函数调用第一个.144 * @param obj145 * @param methodName146 * @param args147 * @return 148 * @return Object 149 * @throws150 * @author feifei.liu151 * @date 2015年9月25日 下午7:56:57152 */153 public static Object invokeMethodByName(final Object obj, final String methodName, final Object[] args) {154 Method method = getAccessibleMethodByName(obj, methodName);155 if (method == null) {156 throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]");157 }158 159 try {160 return method.invoke(obj, args);161 } catch (Exception e) {162 throw convertReflectionExceptionToUnchecked(e);163 }164 }165 166 /**167 * @Description: 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问.168 * 如向上转型到Object仍无法找到, 返回null.169 * @param obj170 * @param fieldName171 * @return 172 * @return Field 173 * @throws174 * @author feifei.liu175 * @date 2015年9月25日 下午7:57:39176 */177 public static Field getAccessibleField(final Object obj, final String fieldName) {178 Validate.notNull(obj, "object can't be null");179 Validate.notBlank(fieldName, "fieldName can't be blank");180 for (Class superClass = obj.getClass(); superClass != Object.class; superClass = superClass181 .getSuperclass()) {182 try {183 Field field = superClass.getDeclaredField(fieldName);184 makeAccessible(field);185 return field;186 } catch (NoSuchFieldException e) { // NOSONAR187 // Field不在当前类定义,继续向上转型188 }189 }190 return null;191 }192 193 /**194 * @Description: 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. 如向上转型到Object仍无法找到, 返回null.195 * 匹配函数名+参数类型.196 * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object...args).197 * @param obj198 * @param methodName199 * @param parameterTypes200 * @return 201 * @return Method 202 * @throws203 * @author feifei.liu204 * @date 2015年9月25日 下午7:57:57205 */206 public static Method getAccessibleMethod(final Object obj, final String methodName,207 final Class ... parameterTypes) {208 Validate.notNull(obj, "object can't be null");209 Validate.notBlank(methodName, "methodName can't be blank");210 211 for (Class searchType = obj.getClass(); searchType != Object.class; searchType = searchType212 .getSuperclass()) {213 try {214 Method method = searchType.getDeclaredMethod(methodName, parameterTypes);215 makeAccessible(method);216 return method;217 } catch (NoSuchMethodException e) {218 // Method不在当前类定义,继续向上转型219 }220 }221 return null;222 }223 224 /**225 * @Description: 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. 如向上转型到Object仍无法找到, 返回null. 只匹配函数名.226 * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object...args)227 * @param obj228 * @param methodName229 * @return 230 * @return Method 231 * @throws232 * @author feifei.liu233 * @date 2015年9月25日 下午7:58:48234 */235 public static Method getAccessibleMethodByName(final Object obj, final String methodName) {236 Validate.notNull(obj, "object can't be null");237 Validate.notBlank(methodName, "methodName can't be blank");238 239 for (Class searchType = obj.getClass(); searchType != Object.class; searchType = searchType240 .getSuperclass()) {241 Method[] methods = searchType.getDeclaredMethods();242 for (Method method : methods) {243 if (method.getName().equals(methodName)) {244 makeAccessible(method);245 return method;246 }247 }248 }249 return null;250 }251 252 /**253 * @Description: 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨254 * @param method 255 * @return void 256 * @throws257 * @author feifei.liu258 * @date 2015年9月25日 下午7:59:24259 */260 public static void makeAccessible(Method method) {261 if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))262 && !method.isAccessible()) {263 method.setAccessible(true);264 }265 }266 267 /**268 * @Description: 改变private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨269 * @param field 270 * @return void 271 * @throws272 * @author feifei.liu273 * @date 2015年9月25日 下午7:59:40274 */275 public static void makeAccessible(Field field) {276 if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers())277 || Modifier.isFinal(field.getModifiers())) && !field.isAccessible()) {278 field.setAccessible(true);279 }280 }281 282 /**283 * @Description: 通过反射, 获得Class定义中声明的泛型参数的类型, 注意泛型必须定义在父类处 如无法找到, 返回Object.class. eg.284 * @param clazz285 * @return 286 * @return Class287 * @throws288 * @author feifei.liu289 * @date 2015年9月25日 下午7:59:53290 */291 @SuppressWarnings({ "unchecked", "rawtypes" })292 public static Class getClassGenricType(final Class clazz) {293 return getClassGenricType(clazz, 0);294 }295 296 /**297 * @Description: 通过反射, 获得Class定义中声明的父类的泛型参数的类型. 如无法找到, 返回Object.class.298 * @param clazz299 * @param index300 * @return 301 * @return Class 302 * @throws303 * @author feifei.liu304 * @date 2015年9月25日 下午8:00:07305 */306 @SuppressWarnings("rawtypes")307 public static Class getClassGenricType(final Class clazz, final int index) {308 309 Type genType = clazz.getGenericSuperclass();310 311 if (!(genType instanceof ParameterizedType)) {312 logger.warn(clazz.getSimpleName() + "'s superclass not ParameterizedType");313 return Object.class;314 }315 316 Type[] params = ((ParameterizedType) genType).getActualTypeArguments();317 318 if ((index >= params.length) || (index < 0)) {319 logger.warn("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "320 + params.length);321 return Object.class;322 }323 if (!(params[index] instanceof Class)) {324 logger.warn(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");325 return Object.class;326 }327 328 return (Class) params[index];329 }330 331 /**332 * @Description: 通过反射,获得当前对象类型333 * @param instance334 * @return 335 * @return Class 336 * @throws337 * @author feifei.liu338 * @date 2015年9月25日 下午8:00:29339 */340 @SuppressWarnings("rawtypes")341 public static Class getUserClass(Object instance) {342 Validate.notNull(instance, "Instance must not be null");343 Class clazz = instance.getClass();344 if ((clazz != null) && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) {345 Class superClass = clazz.getSuperclass();346 if ((superClass != null) && !Object.class.equals(superClass)) {347 return superClass;348 }349 }350 return clazz;351 352 }353 354 /**355 * @Description: 将反射时的checked exception转换为unchecked exception.356 * @param e357 * @return 358 * @return RuntimeException 359 * @throws360 * @author feifei.liu361 * @date 2015年9月25日 下午8:01:08362 */363 public static RuntimeException convertReflectionExceptionToUnchecked(Exception e) {364 if ((e instanceof IllegalAccessException) || (e instanceof IllegalArgumentException)365 || (e instanceof NoSuchMethodException)) {366 return new IllegalArgumentException(e);367 } else if (e instanceof InvocationTargetException) {368 return new RuntimeException(((InvocationTargetException) e).getTargetException());369 } else if (e instanceof RuntimeException) {370 return (RuntimeException) e;371 }372 return new RuntimeException("Unexpected Checked Exception.", e);373 }374 375 /**376 * @Description: 循环向上,获取对象声明的字段377 * @author xiaopeng.ma378 * @date 2017/3/23 17:03379 */380 public static Map getAllDeclaredField(T t) {381 Map map = new HashMap<>();382 if (t != null) {383 Class clazz = t.getClass();384 for (; Object.class != clazz; clazz.getSuperclass()) {385 Field[] declaredFields = clazz.getDeclaredFields();386 for (Field declaredField : declaredFields) {387 map.put(declaredField.getName(), declaredField.getClass().getSimpleName());388 }389 }390 }391 return map;392 }393 394 }