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 }