反射工具类.提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class,被AOP过的真实类等工具函数.java
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 obj 117 * @param methodName 118 * @param parameterTypes 119 * @param args 120 * @return 121 * @return Object 122 * @throws 123 * @author feifei.liu 124 * @date 2015年9月25日 下午7:56:33 125 */ 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 obj 145 * @param methodName 146 * @param args 147 * @return 148 * @return Object 149 * @throws 150 * @author feifei.liu 151 * @date 2015年9月25日 下午7:56:57 152 */ 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 obj 170 * @param fieldName 171 * @return 172 * @return Field 173 * @throws 174 * @author feifei.liu 175 * @date 2015年9月25日 下午7:57:39 176 */ 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 = superClass 181 .getSuperclass()) { 182 try { 183 Field field = superClass.getDeclaredField(fieldName); 184 makeAccessible(field); 185 return field; 186 } catch (NoSuchFieldException e) {// NOSONAR 187 // 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 obj 198 * @param methodName 199 * @param parameterTypes 200 * @return 201 * @return Method 202 * @throws 203 * @author feifei.liu 204 * @date 2015年9月25日 下午7:57:57 205 */ 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 = searchType 212 .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 obj 228 * @param methodName 229 * @return 230 * @return Method 231 * @throws 232 * @author feifei.liu 233 * @date 2015年9月25日 下午7:58:48 234 */ 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 = searchType 240 .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 * @throws 257 * @author feifei.liu 258 * @date 2015年9月25日 下午7:59:24 259 */ 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 * @throws 272 * @author feifei.liu 273 * @date 2015年9月25日 下午7:59:40 274 */ 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 clazz 285 * @return 286 * @return Class<T> 287 * @throws 288 * @author feifei.liu 289 * @date 2015年9月25日 下午7:59:53 290 */ 291 @SuppressWarnings({ "unchecked", "rawtypes" }) 292 public static <T> Class<T> getClassGenricType(final Class clazz) { 293 return getClassGenricType(clazz, 0); 294 } 295 296 /** 297 * @Description: 通过反射, 获得Class定义中声明的父类的泛型参数的类型. 如无法找到, 返回Object.class. 298 * @param clazz 299 * @param index 300 * @return 301 * @return Class 302 * @throws 303 * @author feifei.liu 304 * @date 2015年9月25日 下午8:00:07 305 */ 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 instance 334 * @return 335 * @return Class<?> 336 * @throws 337 * @author feifei.liu 338 * @date 2015年9月25日 下午8:00:29 339 */ 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 e 357 * @return 358 * @return RuntimeException 359 * @throws 360 * @author feifei.liu 361 * @date 2015年9月25日 下午8:01:08 362 */ 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.ma 378 * @date 2017/3/23 17:03 379 */ 380 public static Map<String, String> getAllDeclaredField(T t) { 381 Map<String, String> 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 }