反射工具类.提供调用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 }

猜你喜欢

转载自www.cnblogs.com/zhanghongjie/p/9239846.html