反射工具类.

  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 }

 

posted @ 2019-11-07 21:17  _万古如长夜  阅读(543)  评论(0编辑  收藏  举报