反射工具类.
1 /** 2 * Copyright (c) 2005-2012 springside.org.cn 3 * <p> 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 */ 6 package com.zhouyy.netBank.util; 7 8 import org.slf4j.Logger; 9 import org.slf4j.LoggerFactory; 10 import org.springframework.util.Assert; 11 12 import java.lang.reflect.*; 13 import java.util.ArrayList; 14 import java.util.List; 15 16 /** 17 * 反射工具类. 18 * 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数. 19 * @author calvin 20 * @version 2013-01-15 21 */ 22 @SuppressWarnings("rawtypes") 23 public class Reflections { 24 25 private static final String SETTER_PREFIX = "set"; 26 27 private static final String GETTER_PREFIX = "get"; 28 29 private static final String CGLIB_CLASS_SEPARATOR = "$$"; 30 31 private static Logger logger = LoggerFactory.getLogger(Reflections.class); 32 33 /** 34 * 调用Getter方法. 35 * 支持多级,如:对象名.对象名.方法 36 */ 37 public static Object invokeGetter(Object obj, String propertyName) { 38 Object object = obj; 39 for (String name : StringUtils.split(propertyName, ".")) { 40 String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name); 41 object = invokeMethod(object, getterMethodName, new Class[]{}, new Object[]{}); 42 } 43 return object; 44 } 45 46 /** 47 * 调用Setter方法, 仅匹配方法名。 48 * 支持多级,如:对象名.对象名.方法 49 */ 50 public static void invokeSetter(Object obj, String propertyName, Object value) { 51 Object object = obj; 52 String[] names = StringUtils.split(propertyName, "."); 53 for (int i = 0; i < names.length; i++) { 54 if (i < names.length - 1) { 55 String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]); 56 object = invokeMethod(object, getterMethodName, new Class[]{}, new Object[]{}); 57 } else { 58 String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]); 59 invokeMethodByName(object, setterMethodName, new Object[]{value}); 60 } 61 } 62 } 63 64 /** 65 * 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数. 66 */ 67 public static Object getFieldValue(final Object obj, final String fieldName) { 68 Field field = getAccessibleField(obj, fieldName); 69 70 if (field == null) { 71 throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + obj + "]"); 72 } 73 74 Object result = null; 75 try { 76 result = field.get(obj); 77 } catch (IllegalAccessException e) { 78 logger.error("不可能抛出的异常{}", e.getMessage()); 79 } 80 return result; 81 } 82 83 /** 84 * 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数. 85 */ 86 public static void setFieldValue(final Object obj, final String fieldName, final Object value) { 87 Field field = getAccessibleField(obj, fieldName); 88 89 if (field == null) { 90 throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + obj + "]"); 91 } 92 93 try { 94 field.set(obj, value); 95 } catch (IllegalAccessException e) { 96 logger.error("不可能抛出的异常:{}", e.getMessage()); 97 } 98 } 99 100 /** 101 * 直接调用对象方法, 无视private/protected修饰符. 102 * 用于一次性调用的情况,否则应使用getAccessibleMethod()函数获得Method后反复调用. 103 * 同时匹配方法名+参数类型, 104 */ 105 public static Object invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes, 106 final Object[] args) { 107 Method method = getAccessibleMethod(obj, methodName, parameterTypes); 108 if (method == null) { 109 throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]"); 110 } 111 112 try { 113 return method.invoke(obj, args); 114 } catch (Exception e) { 115 throw convertReflectionExceptionToUnchecked(e); 116 } 117 } 118 119 /** 120 * 直接调用对象方法, 无视private/protected修饰符, 121 * 用于一次性调用的情况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用. 122 * 只匹配函数名,如果有多个同名函数调用第一个。 123 */ 124 public static Object invokeMethodByName(final Object obj, final String methodName, final Object[] args) { 125 Method method = getAccessibleMethodByName(obj, methodName); 126 if (method == null) { 127 throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]"); 128 } 129 130 try { 131 return method.invoke(obj, args); 132 } catch (Exception e) { 133 throw convertReflectionExceptionToUnchecked(e); 134 } 135 } 136 137 /** 138 * 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问. 139 * 140 * 如向上转型到Object仍无法找到, 返回null. 141 */ 142 public static Field getAccessibleField(final Object obj, final String fieldName) { 143 Assert.notNull(obj, "object can't be null"); 144 Assert.hasText(fieldName, "fieldName can't be blank"); 145 for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) { 146 try { 147 Field field = superClass.getDeclaredField(fieldName); 148 makeAccessible(field); 149 return field; 150 } catch (NoSuchFieldException e) {//NOSONAR 151 // Field不在当前类定义,继续向上转型 152 try { 153 Field field = obj.getClass().getField(fieldName); 154 makeAccessible(field); 155 return field; 156 } catch (NoSuchFieldException e1) { 157 continue;// new add 158 } 159 } 160 } 161 return null; 162 } 163 164 /** 165 * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. 166 * 如向上转型到Object仍无法找到, 返回null. 167 * 匹配函数名+参数类型。 168 * 169 * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args) 170 */ 171 public static Method getAccessibleMethod(final Object obj, final String methodName, 172 final Class<?>... parameterTypes) { 173 Assert.notNull(obj, "object can't be null"); 174 Assert.hasText(methodName, "methodName can't be blank"); 175 176 for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) { 177 try { 178 Method method = searchType.getDeclaredMethod(methodName, parameterTypes); 179 makeAccessible(method); 180 return method; 181 } catch (NoSuchMethodException e) { 182 // Method不在当前类定义,继续向上转型 183 continue;// new add 184 } 185 } 186 return null; 187 } 188 189 /** 190 * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. 191 * 如向上转型到Object仍无法找到, 返回null. 192 * 只匹配函数名。 193 * 194 * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args) 195 */ 196 public static Method getAccessibleMethodByName(final Object obj, final String methodName) { 197 Assert.notNull(obj, "object can't be null"); 198 Assert.hasText(methodName, "methodName can't be blank"); 199 200 for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) { 201 Method[] methods = searchType.getDeclaredMethods(); 202 for (Method method : methods) { 203 if (method.getName().equals(methodName)) { 204 makeAccessible(method); 205 return method; 206 } 207 } 208 } 209 return null; 210 } 211 212 /** 213 * 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。 214 */ 215 public static void makeAccessible(Method method) { 216 if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) 217 && !method.isAccessible()) { 218 method.setAccessible(true); 219 } 220 } 221 222 /** 223 * 改变private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。 224 */ 225 public static void makeAccessible(Field field) { 226 if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) || Modifier 227 .isFinal(field.getModifiers())) && !field.isAccessible()) { 228 field.setAccessible(true); 229 } 230 } 231 232 /** 233 * 通过反射, 获得Class定义中声明的泛型参数的类型, 注意泛型必须定义在父类处 234 * 如无法找到, 返回Object.class. 235 * eg. 236 * public UserDao extends HibernateDao<User> 237 * 238 * @param clazz The class to introspect 239 * @return the first generic declaration, or Object.class if cannot be determined 240 */ 241 @SuppressWarnings("unchecked") 242 public static <T> Class<T> getClassGenricType(final Class clazz) { 243 return getClassGenricType(clazz, 0); 244 } 245 246 /** 247 * 通过反射, 获得Class定义中声明的父类的泛型参数的类型. 248 * 如无法找到, 返回Object.class. 249 * 250 * 如public UserDao extends HibernateDao<User,Long> 251 * 252 * @param clazz clazz The class to introspect 253 * @param index the Index of the generic ddeclaration,start from 0. 254 * @return the index generic declaration, or Object.class if cannot be determined 255 */ 256 public static Class getClassGenricType(final Class clazz, final int index) { 257 258 Type genType = clazz.getGenericSuperclass(); 259 if (!(genType instanceof ParameterizedType)) { 260 logger.warn(clazz.getName() + "'s superclass not ParameterizedType"); 261 return Object.class; 262 } 263 264 Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); 265 266 if (index >= params.length || index < 0) { 267 logger.warn("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: " 268 + params.length); 269 return Object.class; 270 } 271 if (!(params[index] instanceof Class)) { 272 logger.warn(clazz.getName() + " not set the actual class on superclass generic parameter"); 273 return Object.class; 274 } 275 276 return (Class) params[index]; 277 } 278 279 public static Class<?> getUserClass(Object instance) { 280 Assert.notNull(instance, "Instance must not be null"); 281 Class clazz = instance.getClass(); 282 if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) { 283 Class<?> superClass = clazz.getSuperclass(); 284 if (superClass != null && !Object.class.equals(superClass)) { 285 return superClass; 286 } 287 } 288 return clazz; 289 290 } 291 292 /** 293 * 将反射时的checked exception转换为unchecked exception. 294 */ 295 public static RuntimeException convertReflectionExceptionToUnchecked(Exception e) { 296 if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException 297 || e instanceof NoSuchMethodException) { 298 return new IllegalArgumentException(e); 299 } else if (e instanceof InvocationTargetException) { 300 return new RuntimeException(((InvocationTargetException) e).getTargetException()); 301 } else if (e instanceof RuntimeException) { 302 return (RuntimeException) e; 303 } 304 return new RuntimeException("Unexpected Checked Exception.", e); 305 } 306 307 308 public static List<Field> fields(Class clzz) { 309 List<Field> result = new ArrayList<Field>(); 310 Field[] fields = clzz.getDeclaredFields(); 311 for (Field field : fields) { 312 result.add(field); 313 } 314 return result; 315 } 316 317 public static List<Field> fields(Class clzz, Class annotation) { 318 List<Field> result = new ArrayList<Field>(); 319 Field[] fields = clzz.getDeclaredFields(); 320 for (Field field : fields) { 321 if (field.isAnnotationPresent(annotation)) { 322 result.add(field); 323 } 324 } 325 return result; 326 } 327 328 public static Field findField(Class clzz, String fieldName) { 329 Field field = null; 330 try { 331 field = clzz.getDeclaredField(fieldName); 332 } catch (Exception e) { 333 if (clzz.getSuperclass() != null) { 334 field = findField(clzz.getSuperclass(), fieldName); 335 } 336 } 337 return field; 338 } 339 340 public static Object field(Class obj, String fieldName) throws Exception { 341 Field field = findField(obj.getClass(), fieldName); 342 field.setAccessible(true); 343 return field.get(obj); 344 } 345 }