Java tutorial
/* * 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); } }