zoukankan      html  css  js  c++  java
  • 反射工具类.

      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 }
  • 相关阅读:
    K近邻(K Nearest Neighbor-KNN)原理讲解及实现
    Bisecting KMeans (二分K均值)算法讲解及实现
    KMeans (K均值)算法讲解及实现
    NodeJs使用async让代码按顺序串行执行
    NodeJs递归删除非空文件夹
    NodeJs之配置文件管理
    NodeJs针对Express框架配置Mysql进行数据库操作
    在Express中使用Multiparty进行文件上传及POST、GET参数获取
    Linux操作命令
    SftpUtil FTP文件上传
  • 原文地址:https://www.cnblogs.com/chinazhou-wang/p/11815709.html
Copyright © 2011-2022 走看看