com.github.dactiv.common.utils.ReflectionUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.github.dactiv.common.utils.ReflectionUtils.java

Source

/*
 * Copyright 2013-2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.github.dactiv.common.utils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

/**
 * ??.
 * 
 * @author maurice
 */

@SuppressWarnings({ "unchecked", "rawtypes" })
public abstract class ReflectionUtils {

    public static final String CGLIB_CLASS_SEPARATOR = "$$";

    private static Logger logger = LoggerFactory.getLogger(ReflectionUtils.class);

    /**
     * Getter.
     * 
     * @param target
     *            Object
     * @param propertyName
     *            ??
     * 
     * @return Object
     */
    public static <T> T invokeGetterMethod(Object target, String propertyName) {
        String getterMethodName = "get" + StringUtils.capitalize(propertyName);
        return (T) invokeMethod(target, getterMethodName, new Class[] {}, new Object[] {});
    }

    /**
     * Setter.valueClass?Setter.
     * 
     * @param target
     *            Object
     * @param propertyName
     *            ??
     * @param value
     *            
     * 
     */
    public static void invokeSetterMethod(Object target, String propertyName, Object value) {
        invokeSetterMethod(target, propertyName, value, null);
    }

    /**
     * Setter.
     * 
     * @param target
     *            Object
     * @param value
     *            
     * @param FieldType
     *            Setter,valueClass.
     */
    public static void invokeSetterMethod(Object target, String propertyName, Object value, Class<?> FieldType) {
        Class<?> type = FieldType != null ? FieldType : value.getClass();
        String setterMethodName = "set" + StringUtils.capitalize(propertyName);
        invokeMethod(target, setterMethodName, new Class[] { type }, new Object[] { value });
    }

    /**
     * , private/protected..
     * 
     * @param target
     *            Object
     * @param methodName
     *            ??
     * @param parameterTypes
     *            ?args?
     * @param args
     *            ?parameterTypes?
     * 
     * @return Object
     */
    public static Object invokeMethod(final Object target, final String methodName, final Class<?>[] parameterTypes,
            final Object[] args) {

        Method method = getAccessibleMethod(target, methodName, parameterTypes);
        if (method == null) {
            throw new IllegalArgumentException(
                    "? [" + methodName + "]  [" + target + "] ");
        }

        try {
            return method.invoke(target, args);
        } catch (Exception e) {
            throw convertReflectionExceptionToUnchecked(e);
        }
    }

    /**
     * obj??fiedlName
     * 
     * @param target
     *            ?
     * @param fieldName
     *            ??
     * 
     * @return boolean
     */
    public static boolean hasField(Object target, String fieldName) {
        return getAccessibleField(target, fieldName) != null;
    }

    /**
     * ?, private/protected, ??getter.
     * 
     * @param target
     *            Object
     * @param fieldName
     *            ??
     * 
     * @return Object
     */
    public static <T> T getFieldValue(final Object target, final String fieldName) {
        Assert.notNull(target, "target?");
        Assert.notNull(fieldName, "fieldName?");

        Field field = getAccessibleField(target, fieldName);

        if (field == null) {
            throw new IllegalArgumentException(
                    "? [" + fieldName + "]   [" + target + "] ");
        }

        Object result = null;
        try {
            result = field.get(target);
        } catch (IllegalAccessException e) {
            logger.error("??{}", e.getMessage());
        }
        return (T) result;
    }

    /**
     * , private/protected, ??setter.
     * 
     * @param target
     *            Object
     * @param fieldName
     *            ??
     * @param value
     *            
     */
    public static void setFieldValue(final Object target, final String fieldName, final Object value) {
        Assert.notNull(target, "target?");
        Assert.notNull(fieldName, "fieldName?");

        Field field = getAccessibleField(target, fieldName);

        if (field == null) {
            throw new IllegalArgumentException(
                    "? [" + fieldName + "]  [" + target + "] ");
        }

        try {
            field.set(target, value);
        } catch (IllegalAccessException e) {
            logger.error("??:{}", e.getMessage());
        }
    }

    /**
     * ?, ?DeclaredField, ?.?Object?, null.
     * 
     * @param target
     *            Object
     * @param fieldName
     *            ??
     * 
     * @return {@link Field}
     */
    public static Field getAccessibleField(final Object target, final String fieldName) {
        Assert.notNull(target, "target?");
        return getAccessibleField(getTargetClass(target), fieldName);
    }

    /**
     * ?, ?DeclaredField, ?.
     * 
     * ?Object?, null.
     * 
     * @param targetClass
     *            Class
     * @param fieldName
     *            class??
     * 
     * @return {@link Field}
     */
    public static Field getAccessibleField(final Class targetClass, final String fieldName) {
        Assert.notNull(targetClass, "targetClass?");
        Assert.hasText(fieldName, "fieldName?");
        for (Class<?> superClass = targetClass; superClass != Object.class; superClass = superClass
                .getSuperclass()) {
            try {
                Field field = superClass.getDeclaredField(fieldName);
                field.setAccessible(true);
                return field;
            } catch (NoSuchFieldException e) {
            }
        }
        return null;
    }

    /**
     * ?, ?DeclaredField, ?.
     * 
     * @param target 
     * 
     * @return List
     */
    public static List<Field> getAccessibleFields(final Object target) {
        Assert.notNull(target, "target?");
        return getAccessibleFields(getTargetClass(target));
    }

    /**
     * ?, ?DeclaredField, ?.
     * 
     * @param targetClass
     *            Class
     * 
     * @return List
     */
    public static List<Field> getAccessibleFields(final Class targetClass) {
        return getAccessibleFields(targetClass, false);
    }

    /**
     * ?DeclaredField,?.
     * 
     * @param targetClass
     *            Class
     * @param ignoreParent
     *            ??,?Field
     * 
     * @return List
     */
    public static List<Field> getAccessibleFields(final Class targetClass, final boolean ignoreParent) {
        Assert.notNull(targetClass, "targetClass?");
        List<Field> fields = new ArrayList<Field>();

        Class<?> sc = targetClass;

        do {
            Field[] result = sc.getDeclaredFields();

            if (!ArrayUtils.isEmpty(result)) {

                for (Field field : result) {
                    field.setAccessible(true);
                }

                CollectionUtils.addAll(fields, result);
            }

            sc = sc.getSuperclass();

        } while (sc != Object.class && !ignoreParent);

        return fields;
    }

    /**
     * ?, ?DeclaredMethod,?. ?Object?, null.
     * 
     * ?. ?Method,?Method.invoke(Object obj, Object...
     * args)
     * 
     * @param target
     *            Object
     * @param methodName
     *            ??
     * @param parameterTypes
     *            ?
     * 
     * @return {@link Method}
     */
    public static Method getAccessibleMethod(final Object target, final String methodName,
            Class<?>... parameterTypes) {
        Assert.notNull(target, "target?");
        return getAccessibleMethod(getTargetClass(target), methodName, parameterTypes);
    }

    /**
     * ?, ?DeclaredMethod,?. ?Object?, null.
     * 
     * ?. ?Method,?Method.invoke(Object obj, Object...
     * args)
     * 
     * @param targetClass
     *            Class
     * @param parameterTypes
     *            ?
     * 
     * @return {@link Method}
     */
    public static Method getAccessibleMethod(final Class targetClass, final String methodName,
            Class<?>... parameterTypes) {
        Assert.notNull(targetClass, "targetClass?");
        Assert.notNull(methodName, "methodName?");

        for (Class<?> superClass = targetClass; superClass != Object.class; superClass = superClass
                .getSuperclass()) {
            try {
                Method method = superClass.getDeclaredMethod(methodName, parameterTypes);
                method.setAccessible(true);
                return method;
            } catch (NoSuchMethodException e) {
            }
        }
        return null;
    }

    /**
     * ?, ?DeclaredMethod ?.
     * 
     * @param target
     *            Object
     * 
     * @return List
     */
    public static List<Method> getAccessibleMethods(final Object target) {
        Assert.notNull(target, "target?");
        return getAccessibleMethods(getTargetClass(target));
    }

    /**
     * ?, ?DeclaredMethod ?.
     * 
     * @param targetClass
     *            Class
     * 
     * @return List
     */
    public static List<Method> getAccessibleMethods(final Class targetClass) {
        return getAccessibleMethods(targetClass, false);
    }

    /**
     * ?DeclaredMethod ?.
     * 
     * @param targetClass
     *            Class
     * @param ignoreParent
     *            ??,?Method
     * 
     * @return List
     */
    public static List<Method> getAccessibleMethods(final Class targetClass, boolean ignoreParent) {
        Assert.notNull(targetClass, "targetClass?");
        List<Method> methods = new ArrayList<Method>();

        Class<?> superClass = targetClass;
        do {
            Method[] result = superClass.getDeclaredMethods();

            if (!ArrayUtils.isEmpty(result)) {

                for (Method method : result) {
                    method.setAccessible(true);
                }

                CollectionUtils.addAll(methods, result);
            }

            superClass = superClass.getSuperclass();
        } while (superClass != Object.class && !ignoreParent);

        return methods;
    }

    /**
     * ?
     * 
     * @param target
     *            Object
     * @param annotationClass
     *            
     * 
     * @return Object
     */
    public static <T> T getAnnotation(Object target, Class annotationClass) {
        Assert.notNull(target, "target?");
        return (T) getAnnotation(target.getClass(), annotationClass);
    }

    /**
     * ?
     * 
     * @param targetClass
     *            Class
     * @param annotationClass
     *            Class
     * 
     * @return Object
     */
    public static <T extends Annotation> T getAnnotation(Class targetClass, Class annotationClass) {
        Assert.notNull(targetClass, "targetClass?");
        Assert.notNull(annotationClass, "annotationClass?");

        if (targetClass.isAnnotationPresent(annotationClass)) {
            return (T) targetClass.getAnnotation(annotationClass);
        }

        return null;
    }

    /**
     * ?ObjectannotationClass
     * 
     * @param target
     *            Object
     * @param annotationClass
     *            Annotation
     * 
     * @return {@link Annotation}
     */
    public static <T extends Annotation> List<T> getAnnotations(Object target, Class annotationClass) {
        Assert.notNull(target, "target?");
        return getAnnotations(getTargetClass(target), annotationClass);
    }

    /**
     * 
     * ?annotationClass
     * 
     * @param targetClass
     *            Class
     * @param annotationClass
     *            Class
     * 
     * @return List
     */
    public static <T extends Annotation> List<T> getAnnotations(Class targetClass, Class annotationClass) {
        Assert.notNull(targetClass, "targetClass?");
        Assert.notNull(annotationClass, "annotationClass?");

        List<T> result = new ArrayList<T>();
        Annotation annotation = targetClass.getAnnotation(annotationClass);
        if (annotation != null) {
            result.add((T) annotation);
        }
        Constructor[] constructors = targetClass.getDeclaredConstructors();
        // ?
        CollectionUtils.addAll(result, getAnnotations(constructors, annotationClass).iterator());

        Field[] fields = targetClass.getDeclaredFields();
        // ?
        CollectionUtils.addAll(result, getAnnotations(fields, annotationClass).iterator());

        Method[] methods = targetClass.getDeclaredMethods();
        // ?
        CollectionUtils.addAll(result, getAnnotations(methods, annotationClass).iterator());

        for (Class<?> superClass = targetClass.getSuperclass(); superClass == null
                || superClass == Object.class; superClass = superClass.getSuperclass()) {
            List<T> temp = getAnnotations(superClass, annotationClass);
            if (CollectionUtils.isNotEmpty(temp)) {
                CollectionUtils.addAll(result, temp.iterator());
            }
        }

        return result;
    }

    /**
     * ?fieldannotationClass
     * 
     * @param field
     *            field
     * @param annotationClass
     *            annotationClass
     * 
     * @return {@link Annotation}
     */
    public static <T extends Annotation> T getAnnotation(Field field, Class annotationClass) {

        Assert.notNull(field, "field?");
        Assert.notNull(annotationClass, "annotationClass?");

        field.setAccessible(true);
        if (field.isAnnotationPresent(annotationClass)) {
            return (T) field.getAnnotation(annotationClass);
        }
        return null;
    }

    /**
     * ?field?annotationClass
     * 
     * @param fields
     *            field
     * @param annotationClass
     *            annotationClass
     * 
     * @return List
     */
    public static <T extends Annotation> List<T> getAnnotations(Field[] fields, Class annotationClass) {

        if (ArrayUtils.isEmpty(fields)) {
            return null;
        }

        List<T> result = new ArrayList<T>();

        for (Field field : fields) {
            field.setAccessible(true);
            Annotation annotation = getAnnotation(field, annotationClass);
            if (annotation != null) {
                result.add((T) annotation);
            }
        }

        return result;
    }

    /**
     * ?methodannotationClass
     * 
     * @param method
     *            method
     * @param annotationClass
     *            annotationClass
     * 
     * @return {@link Annotation}
     */
    public static <T extends Annotation> T getAnnotation(Method method, Class annotationClass) {

        Assert.notNull(method, "method?");
        Assert.notNull(annotationClass, "annotationClass?");

        method.setAccessible(true);
        if (method.isAnnotationPresent(annotationClass)) {
            return (T) method.getAnnotation(annotationClass);
        }
        return null;
    }

    /**
     * ?method?annotationClass
     * 
     * @param methods
     *            method
     * @param annotationClass
     *            annotationClass
     * 
     * @return List
     */
    public static <T extends Annotation> List<T> getAnnotations(Method[] methods, Class annotationClass) {

        if (ArrayUtils.isEmpty(methods)) {
            return null;
        }

        List<T> result = new ArrayList<T>();

        for (Method method : methods) {

            Annotation annotation = getAnnotation(method, annotationClass);
            if (annotation != null) {
                result.add((T) annotation);
            }
        }

        return result;
    }

    /**
     * ?constructorannotationClass
     * 
     * @param constructor
     *            constructor
     * @param annotationClass
     *            annotationClass
     * 
     * @return {@link Annotation}
     */
    public static <T extends Annotation> T getAnnotation(Constructor constructor, Class annotationClass) {

        Assert.notNull(constructor, "constructor?");
        Assert.notNull(annotationClass, "annotationClass?");

        constructor.setAccessible(true);

        if (constructor.isAnnotationPresent(annotationClass)) {
            return (T) constructor.getAnnotation(annotationClass);
        }

        return null;
    }

    /**
     * ?constructors?annotationClass
     * 
     * @param constructors
     *            constructor
     * @param annotationClass
     *            annotationClass
     * 
     * @return List
     */
    public static <T extends Annotation> List<T> getAnnotations(Constructor[] constructors, Class annotationClass) {

        if (ArrayUtils.isEmpty(constructors)) {
            return null;
        }

        List<T> result = new ArrayList<T>();

        for (Constructor constructor : constructors) {
            Annotation annotation = getAnnotation(constructor, annotationClass);
            if (annotation != null) {
                result.add((T) annotation);
            }
        }

        return result;
    }

    /**
     * 
     * ?o??
     * 
     * @param targetClass
     *            Class
     * @param type
     *            ????
     * 
     * @return List
     */
    public static List<String> getAccessibleFieldNames(final Class targetClass, Class type) {

        Assert.notNull(targetClass, "targetClass?");
        Assert.notNull(type, "type?");

        List<String> list = new ArrayList<String>();

        for (Field field : targetClass.getDeclaredFields()) {
            if (field.getType().equals(type)) {
                list.add(field.getName());
            }
        }

        return list;
    }

    /**
     * ??, Class?. , Object.class??
     * 
     * <pre>
     * 
     * public UserDao extends HibernateDao<User>
     * </pre>
     * 
     * @param targetClass
     *            ???Class
     * @return Object.clssT.class
     */
    public static <T> Class<T> getSuperClassGenricType(final Class targetClass) {
        return getSuperClassGenricType(targetClass, 0);
    }

    /**
     * ??, Class?. , Object.class.??
     * 
     * <pre>
     * 
     * public UserDao extends HibernateDao<User,Long>
     * </pre>
     * 
     * @param targetClass
     *            ???Class
     * @param index
     *            ?????
     * 
     * @return class
     */
    public static Class getSuperClassGenricType(final Class targetClass, final int index) {

        Assert.notNull(targetClass, "targetClass?");

        Type genType = targetClass.getGenericSuperclass();

        if (!(genType instanceof ParameterizedType)) {
            logger.warn(targetClass.getSimpleName() + "'s superclass not ParameterizedType");
            return Object.class;
        }

        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();

        if (index >= params.length || index < 0) {
            logger.warn("Index: " + index + ", Size of " + targetClass.getSimpleName() + "'s Parameterized Type: "
                    + params.length);
            return Object.class;
        }
        if (!(params[index] instanceof Class)) {
            logger.warn(targetClass.getSimpleName()
                    + " not set the actual Class targetClassn superclass generic parameter");
            return Object.class;
        }

        return (Class) params[index];
    }

    /**
     * Class
     * 
     * @param targetClass
     *            Class
     * 
     * @return Object
     */
    public static <T> T newInstance(Class targetClass) {
        Assert.notNull(targetClass, "targetClass?");
        try {
            return (T) targetClass.newInstance();
        } catch (Exception e) {
            throw convertReflectionExceptionToUnchecked(e);
        }

    }

    /**
     * ?Classcglib AOPCGLIBClass?Class
     * 
     * @param target  
     * 
     * @return Class
     */
    public static Class<?> getTargetClass(Object target) {
        Assert.notNull(target, "target?");
        return getTargetClass(target.getClass());

    }

    /**
     * ?Classcglib AOPCGLIBClass?Class
     * 
     * @param targetClass  class
     * 
     * @return Class
     */
    public static Class<?> getTargetClass(Class<?> targetClass) {

        Assert.notNull(targetClass, "targetClass?");

        Class clazz = targetClass;
        if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) {
            Class<?> superClass = clazz.getSuperclass();
            if (superClass != null && !Object.class.equals(superClass)) {
                return superClass;
            }
        }
        return clazz;
    }

    /**
     * ??checked exception?unchecked exception.
     * 
     * @param e
     *            checked exception
     * 
     *            return {@link RuntimeException}
     */
    public static RuntimeException convertReflectionExceptionToUnchecked(Exception e) {
        if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException
                || e instanceof NoSuchMethodException) {
            return new IllegalArgumentException("Reflection Exception.", e);
        } else if (e instanceof InvocationTargetException) {
            return new RuntimeException("Reflection Exception.",
                    ((InvocationTargetException) e).getTargetException());
        } else if (e instanceof RuntimeException) {
            return (RuntimeException) e;
        }
        return new RuntimeException("Unexpected Checked Exception.", e);
    }

}