• 反射工具类源码


      JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

      Java Reflection

        Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法

      Java反射机制提供的功能

        在运行时判断任意一个对象所属的类

        在运行时构造任意一个类的对象

        在运行时判断任意一个类所具有的成员变量和方法

        在运行时调用任意一个对象的成员变量和方法

        生成动态代理

      反射相关的主要API:

        java.lang.Class:代表一个类

        java.lang.reflect.Method:代表类的方法

        java.lang.reflect.Field:代表类的成员变量

        java.lang.reflect.Constructor:代表类的构造方法

      。。。。。。

      1 import java.lang.reflect.Field;
      2 import java.lang.reflect.InvocationTargetException;
      3 import java.lang.reflect.Method;
      4 import java.lang.reflect.Modifier;
      5 import java.lang.reflect.ParameterizedType;
      6 import java.lang.reflect.Type;
      7 
      8 import org.apache.commons.lang3.StringUtils;
      9 import org.apache.commons.lang3.Validate;
     10 import org.slf4j.Logger;
     11 import org.slf4j.LoggerFactory;
     12 import org.springframework.util.Assert;
     13 
     14 /**
     15  * 反射工具类.
     16  * 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数.
     17  */
     18 //压制警告,即去除警告 
     19 @SuppressWarnings("rawtypes")
     20 public class Reflections {
     21     
     22     private static final String SETTER_PREFIX = "set";
     23 
     24     private static final String GETTER_PREFIX = "get";
     25 
     26     private static final String CGLIB_CLASS_SEPARATOR = "$$";
     27     
     28     private static Logger logger = LoggerFactory.getLogger(Reflections.class);
     29 
     30     /**
     31      * 调用Getter方法.
     32      * 支持多级,如:对象名.对象名.方法
     33      */
     34     public static Object invokeGetter(Object obj, String propertyName) {
     35         Object object = obj;
     36         for (String name : StringUtils.split(propertyName, ".")){
     37             String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name);
     38             object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});
     39         }
     40         return object;
     41     }
     42 
     43     /**
     44      * 调用Setter方法, 仅匹配方法名。
     45      * 支持多级,如:对象名.对象名.方法
     46      */
     47     public static void invokeSetter(Object obj, String propertyName, Object value) {
     48         Object object = obj;
     49         String[] names = StringUtils.split(propertyName, ".");
     50         for (int i=0; i<names.length; i++){
     51             if(i<names.length-1){
     52                 String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]);
     53                 object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});
     54             }else{
     55                 String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]);
     56                 invokeMethodByName(object, setterMethodName, new Object[] { value });
     57             }
     58         }
     59     }
     60 
     61     /**
     62      * 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数.
     63      */
     64     public static Object getFieldValue(final Object obj, final String fieldName) {
     65         Field field = getAccessibleField(obj, fieldName);
     66 
     67         if (field == null) {
     68             throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + obj + "]");
     69         }
     70 
     71         Object result = null;
     72         try {
     73             result = field.get(obj);
     74         } catch (IllegalAccessException e) {
     75             logger.error("不可能抛出的异常{}", e.getMessage());
     76         }
     77         return result;
     78     }
     79 
     80     /**
     81      * 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数.
     82      */
     83     public static void setFieldValue(final Object obj, final String fieldName, final Object value) {
     84         Field field = getAccessibleField(obj, fieldName);
     85 
     86         if (field == null) {
     87             throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + obj + "]");
     88         }
     89 
     90         try {
     91             field.set(obj, value);
     92         } catch (IllegalAccessException e) {
     93             logger.error("不可能抛出的异常:{}", e.getMessage());
     94         }
     95     }
     96 
     97     /**
     98      * 直接调用对象方法, 无视private/protected修饰符.
     99      * 用于一次性调用的情况,否则应使用getAccessibleMethod()函数获得Method后反复调用.
    100      * 同时匹配方法名+参数类型,
    101      */
    102     public static Object invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes,
    103             final Object[] args) {
    104         Method method = getAccessibleMethod(obj, methodName, parameterTypes);
    105         if (method == null) {
    106             throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]");
    107         }
    108 
    109         try {
    110             return method.invoke(obj, args);
    111         } catch (Exception e) {
    112             throw convertReflectionExceptionToUnchecked(e);
    113         }
    114     }
    115 
    116     /**
    117      * 直接调用对象方法, 无视private/protected修饰符,
    118      * 用于一次性调用的情况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用.
    119      * 只匹配函数名,如果有多个同名函数调用第一个。
    120      */
    121     public static Object invokeMethodByName(final Object obj, final String methodName, final Object[] args) {
    122         Method method = getAccessibleMethodByName(obj, methodName);
    123         if (method == null) {
    124             throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]");
    125         }
    126 
    127         try {
    128             return method.invoke(obj, args);
    129         } catch (Exception e) {
    130             throw convertReflectionExceptionToUnchecked(e);
    131         }
    132     }
    133 
    134     /**
    135      * 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问.
    136      * 
    137      * 如向上转型到Object仍无法找到, 返回null.
    138      */
    139     public static Field getAccessibleField(final Object obj, final String fieldName) {
    140         Validate.notNull(obj, "object can't be null");
    141         Validate.notBlank(fieldName, "fieldName can't be blank");
    142         for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {
    143             try {
    144                 Field field = superClass.getDeclaredField(fieldName);
    145                 makeAccessible(field);
    146                 return field;
    147             } catch (NoSuchFieldException e) {//NOSONAR
    148                 // Field不在当前类定义,继续向上转型
    149                 continue;// new add
    150             }
    151         }
    152         return null;
    153     }
    154 
    155     /**
    156      * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
    157      * 如向上转型到Object仍无法找到, 返回null.
    158      * 匹配函数名+参数类型。
    159      * 
    160      * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
    161      */
    162     public static Method getAccessibleMethod(final Object obj, final String methodName,
    163             final Class<?>... parameterTypes) {
    164         Validate.notNull(obj, "object can't be null");
    165         Validate.notBlank(methodName, "methodName can't be blank");
    166 
    167         for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) {
    168             try {
    169                 Method method = searchType.getDeclaredMethod(methodName, parameterTypes);
    170                 makeAccessible(method);
    171                 return method;
    172             } catch (NoSuchMethodException e) {
    173                 // Method不在当前类定义,继续向上转型
    174                 continue;// new add
    175             }
    176         }
    177         return null;
    178     }
    179 
    180     /**
    181      * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
    182      * 如向上转型到Object仍无法找到, 返回null.
    183      * 只匹配函数名。
    184      * 
    185      * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
    186      */
    187     public static Method getAccessibleMethodByName(final Object obj, final String methodName) {
    188         Validate.notNull(obj, "object can't be null");
    189         Validate.notBlank(methodName, "methodName can't be blank");
    190 
    191         for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) {
    192             Method[] methods = searchType.getDeclaredMethods();
    193             for (Method method : methods) {
    194                 if (method.getName().equals(methodName)) {
    195                     makeAccessible(method);
    196                     return method;
    197                 }
    198             }
    199         }
    200         return null;
    201     }
    202 
    203     /**
    204      * 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
    205      */
    206     public static void makeAccessible(Method method) {
    207         if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
    208                 && !method.isAccessible()) {
    209             method.setAccessible(true);
    210         }
    211     }
    212 
    213     /**
    214      * 改变private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
    215      */
    216     public static void makeAccessible(Field field) {
    217         if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) || Modifier
    218                 .isFinal(field.getModifiers())) && !field.isAccessible()) {
    219             field.setAccessible(true);
    220         }
    221     }
    222 
    223     /**
    224      * 通过反射, 获得Class定义中声明的泛型参数的类型, 注意泛型必须定义在父类处
    225      * 如无法找到, 返回Object.class.
    226      * eg.
    227      * public UserDao extends HibernateDao<User>
    228      *
    229      * @param clazz The class to introspect
    230      * @return the first generic declaration, or Object.class if cannot be determined
    231      */
    232     @SuppressWarnings("unchecked")
    233     public static <T> Class<T> getClassGenricType(final Class clazz) {
    234         return getClassGenricType(clazz, 0);
    235     }
    236 
    237     /**
    238      * 通过反射, 获得Class定义中声明的父类的泛型参数的类型.
    239      * 如无法找到, 返回Object.class.
    240      * 
    241      * 如public UserDao extends HibernateDao<User,Long>
    242      *
    243      * @param clazz clazz The class to introspect
    244      * @param index the Index of the generic ddeclaration,start from 0.
    245      * @return the index generic declaration, or Object.class if cannot be determined
    246      */
    247     public static Class getClassGenricType(final Class clazz, final int index) {
    248 
    249         Type genType = clazz.getGenericSuperclass();
    250 
    251         if (!(genType instanceof ParameterizedType)) {
    252             logger.warn(clazz.getSimpleName() + "'s superclass not ParameterizedType");
    253             return Object.class;
    254         }
    255 
    256         Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
    257 
    258         if (index >= params.length || index < 0) {
    259             logger.warn("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "
    260                     + params.length);
    261             return Object.class;
    262         }
    263         if (!(params[index] instanceof Class)) {
    264             logger.warn(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
    265             return Object.class;
    266         }
    267 
    268         return (Class) params[index];
    269     }
    270     
    271     public static Class<?> getUserClass(Object instance) {
    272         Assert.notNull(instance, "Instance must not be null");
    273         Class clazz = instance.getClass();
    274         if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) {
    275             Class<?> superClass = clazz.getSuperclass();
    276             if (superClass != null && !Object.class.equals(superClass)) {
    277                 return superClass;
    278             }
    279         }
    280         return clazz;
    281 
    282     }
    283     
    284     /**
    285      * 将反射时的checked exception转换为unchecked exception.
    286      */
    287     public static RuntimeException convertReflectionExceptionToUnchecked(Exception e) {
    288         if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException
    289                 || e instanceof NoSuchMethodException) {
    290             return new IllegalArgumentException(e);
    291         } else if (e instanceof InvocationTargetException) {
    292             return new RuntimeException(((InvocationTargetException) e).getTargetException());
    293         } else if (e instanceof RuntimeException) {
    294             return (RuntimeException) e;
    295         }
    296         return new RuntimeException("Unexpected Checked Exception.", e);
    297     }
    298 }

    转载请注明出处!

    http://www.cnblogs.com/libingbin/

    感谢您的阅读。如果文章对您有用,那么请轻轻点个赞,以资鼓励。

  • 相关阅读:
    纯js面试题
    js面试题汇总:
    css面试题-圣杯布局
    6.1 React组件 Component的两个问题
    7.1 React异步加载
    vscode插件配置jsx:
    6.2 React renderProps 和 HOC组件优化
    2.5 React高阶组件HOC
    04 Python学习之数据类型-bytes
    03 Python学习之Python基础
  • 原文地址:https://www.cnblogs.com/libingbin/p/6033289.html
Copyright © 2020-2023  润新知