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 }