package org.springside.modules.utils.reflect; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.IdentityHashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ClassUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * 获取Class信息的工具类 * * 1. 取shortClassName 和 packageName * * 2. 获取全部父类,全部接口,以及全部Annotation * * 3. 获取标注了annotation的所有属性和方法 * * 4. 获取方法与属性 (兼容了原始类型的参数, 并默认将方法与属性设为可访问) * * 5. 其他杂项 * * @author calvin */ public class ClassUtil { private static final String CGLIB_CLASS_SEPARATOR = "$$"; private static Logger logger = LoggerFactory.getLogger(ClassUtil.class); private static final Map<Class<?>, Class<?>> primitiveWrapperTypeMap = new IdentityHashMap<Class<?>, Class<?>>(8); static { primitiveWrapperTypeMap.put(Boolean.class, Boolean.TYPE); ClassUtil.primitiveWrapperTypeMap.put(Byte.class, Byte.TYPE); ClassUtil.primitiveWrapperTypeMap.put(Character.class, Character.TYPE); ClassUtil.primitiveWrapperTypeMap.put(Double.class, Double.TYPE); ClassUtil.primitiveWrapperTypeMap.put(Float.class, Float.TYPE); ClassUtil.primitiveWrapperTypeMap.put(Integer.class, Integer.TYPE); ClassUtil.primitiveWrapperTypeMap.put(Long.class, Long.TYPE); ClassUtil.primitiveWrapperTypeMap.put(Short.class, Short.TYPE); } private static final String SETTER_PREFIX = "set"; private static final String GETTER_PREFIX = "get"; private static final String IS_PREFIX = "is"; ////////// shortClassName 和 packageName////////// /** * 返回Class名, 不包含PackageName. * * 内部类的话,返回"主类.内部类" */ public static String getShortClassName(final Class<?> cls) { return ClassUtils.getShortClassName(cls); } /** * 返回Class名,不包含PackageName * * 内部类的话,返回"主类.内部类" */ public static String getShortClassName(final String className) { return ClassUtils.getShortClassName(className); } /** * 返回PackageName */ public static String getPackageName(final Class<?> cls) { return ClassUtils.getPackageName(cls); } /** * 返回PackageName */ public static String getPackageName(final String className) { return ClassUtils.getPackageName(className); } ////////// 获取全部父类,全部接口,以及全部Annotation////////// /** * 递归返回所有的SupperClasses,包含Object.class */ public static List<Class<?>> getAllSuperclasses(final Class<?> cls) { return ClassUtils.getAllSuperclasses(cls); } /** * 递归返回本类及所有基类继承的接口,及接口继承的接口,比Spring中的相同实现完整 */ public static List<Class<?>> getAllInterfaces(final Class<?> cls) { return ClassUtils.getAllInterfaces(cls); } /** * 递归Class所有的Annotation,一个最彻底的实现. * * 包括所有基类,所有接口的Annotation,同时支持Spring风格的Annotation继承的父Annotation, */ public static Set<Annotation> getAllAnnotations(final Class<?> cls) { List<Class<?>> allTypes = getAllSuperclasses(cls); allTypes.addAll(getAllInterfaces(cls)); allTypes.add(cls); Set<Annotation> anns = new HashSet<Annotation>(); for (Class<?> type : allTypes) { anns.addAll(Arrays.asList(type.getDeclaredAnnotations())); } Set<Annotation> superAnnotations = new HashSet<Annotation>(); for (Annotation ann : anns) { getSupperAnnotations(ann.annotationType(), superAnnotations); } anns.addAll(superAnnotations); return anns; } private static <A extends Annotation> void getSupperAnnotations(Class<A> annotationType, Set<Annotation> visited) { Annotation[] anns = annotationType.getDeclaredAnnotations(); for (Annotation ann : anns) { if (!ann.annotationType().getName().startsWith("java.lang") && visited.add(ann)) { getSupperAnnotations(ann.annotationType(), visited); } } } //// 获取标注了annotation的所有属性和方法//////// /** * 找出所有标注了该annotation的公共属性,循环遍历父类. * * 暂未支持Spring风格Annotation继承Annotation * * from org.unitils.util.AnnotationUtils */ public static <T extends Annotation> Set<Field> getAnnotatedPublicFields(Class<? extends Object> clazz, Class<T> annotation) { if (Object.class.equals(clazz)) { return Collections.emptySet(); } Set<Field> annotatedFields = new HashSet<Field>(); Field[] fields = clazz.getFields(); for (Field field : fields) { if (field.getAnnotation(annotation) != null) { annotatedFields.add(field); } } return annotatedFields; } /** * 找出所有标注了该annotation的属性,循环遍历父类,包含private属性. * * 暂未支持Spring风格Annotation继承Annotation * * from org.unitils.util.AnnotationUtils */ public static <T extends Annotation> Set<Field> getAnnotatedFields(Class<? extends Object> clazz, Class<T> annotation) { if (Object.class.equals(clazz)) { return Collections.emptySet(); } Set<Field> annotatedFields = new HashSet<Field>(); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { if (field.getAnnotation(annotation) != null) { annotatedFields.add(field); } } annotatedFields.addAll(getAnnotatedFields(clazz.getSuperclass(), annotation)); return annotatedFields; } /** * 找出所有标注了该annotation的公共方法(含父类的公共函数),循环其接口. * * 暂未支持Spring风格Annotation继承Annotation * * 另,如果子类重载父类的公共函数,父类函数上的annotation不会继承,只有接口上的annotation会被继承. */ public static <T extends Annotation> Set<Method> getAnnotatedPublicMethods(Class<?> clazz, Class<T> annotation) { // 已递归到Objebt.class, 停止递归 if (Object.class.equals(clazz)) { return Collections.emptySet(); } List<Class<?>> ifcs = ClassUtils.getAllInterfaces(clazz); Set<Method> annotatedMethods = new HashSet<Method>(); // 遍历当前类的所有公共方法 Method[] methods = clazz.getMethods(); for (Method method : methods) { // 如果当前方法有标注,或定义了该方法的所有接口有标注 if (method.getAnnotation(annotation) != null || searchOnInterfaces(method, annotation, ifcs)) { annotatedMethods.add(method); } } return annotatedMethods; } private static <T extends Annotation> boolean searchOnInterfaces(Method method, Class<T> annotationType, List<Class<?>> ifcs) { for (Class<?> iface : ifcs) { try { Method equivalentMethod = iface.getMethod(method.getName(), method.getParameterTypes()); if (equivalentMethod.getAnnotation(annotationType) != null) { return true; } } catch (NoSuchMethodException ex) { // Skip this interface - it doesn't have the method... } } return false; } ///////// 获取方法//// /** * 循环遍历,按属性名获取前缀为get或is的函数,并设为可访问 */ public static Method getSetterMethod(Class<?> clazz, String propertyName, Class<?> parameterType) { String setterMethodName = ClassUtil.SETTER_PREFIX + StringUtils.capitalize(propertyName); return ClassUtil.getAccessibleMethod(clazz, setterMethodName, parameterType); } /** * 循环遍历,按属性名获取前缀为set的函数,并设为可访问 */ public static Method getGetterMethod(Class<?> clazz, String propertyName) { String getterMethodName = ClassUtil.GETTER_PREFIX + StringUtils.capitalize(propertyName); Method method = ClassUtil.getAccessibleMethod(clazz, getterMethodName); // retry on another name if (method == null) { getterMethodName = ClassUtil.IS_PREFIX + StringUtils.capitalize(propertyName); method = ClassUtil.getAccessibleMethod(clazz, getterMethodName); } return method; } /** * 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问. * * 如向上转型到Object仍无法找到, 返回null. * * 因为class.getFiled(); 不能获取父类的private函数, 因此采用循环向上的getDeclaredField(); */ public static Field getAccessibleField(final Class clazz, final String fieldName) { Validate.notNull(clazz, "clazz can't be null"); Validate.notEmpty(fieldName, "fieldName can't be blank"); for (Class<?> superClass = clazz; superClass != Object.class; superClass = superClass.getSuperclass()) { try { Field field = superClass.getDeclaredField(fieldName); ClassUtil.makeAccessible(field); return field; } catch (NoSuchFieldException e) {// NOSONAR // Field不在当前类定义,继续向上转型 } } return null; } /** * 循环向上转型, 获取对象的DeclaredMethod, 并强制设置为可访问. * * 如向上转型到Object仍无法找到, 返回null. * * 匹配函数名+参数类型. * * 因为class.getMethod() 不能获取父类的private函数, 因此采用循环向上的getDeclaredMethod(); */ public static Method getAccessibleMethod(final Class<?> clazz, final String methodName, Class<?>... parameterTypes) { Validate.notNull(clazz, "class can't be null"); Validate.notEmpty(methodName, "methodName can't be blank"); Class[] theParameterTypes = ArrayUtils.nullToEmpty(parameterTypes); // 处理原子类型与对象类型的兼容 ClassUtil.wrapClassses(theParameterTypes); for (Class<?> searchType = clazz; searchType != Object.class; searchType = searchType.getSuperclass()) { try { Method method = searchType.getDeclaredMethod(methodName, theParameterTypes); ClassUtil.makeAccessible(method); return method; } catch (NoSuchMethodException e) { // Method不在当前类定义,继续向上转型 } } return null; } /** * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. * * 如向上转型到Object仍无法找到, 返回null. * * 只匹配函数名, 如果有多个同名函数返回第一个 * * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args) * * 因为class.getMethods() 不能获取父类的private函数, 因此采用循环向上的getMethods(); */ public static Method getAccessibleMethodByName(final Class clazz, final String methodName) { Validate.notNull(clazz, "clazz can't be null"); Validate.notEmpty(methodName, "methodName can't be blank"); for (Class<?> searchType = clazz; searchType != Object.class; searchType = searchType.getSuperclass()) { Method[] methods = searchType.getDeclaredMethods(); for (Method method : methods) { if (method.getName().equals(methodName)) { ClassUtil.makeAccessible(method); return method; } } } return null; } /** * 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。 */ public static void makeAccessible(Method method) { if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) && !method.isAccessible()) { method.setAccessible(true); } } /** * 改变private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。 */ public static void makeAccessible(Field field) { if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) || Modifier.isFinal(field.getModifiers())) && !field.isAccessible()) { field.setAccessible(true); } } /** * 兼容原子类型与非原子类型的转换,不考虑依赖两者不同来区分不同函数的场景 */ private static void wrapClassses(Class<?>[] source) { for (int i = 0; i < source.length; i++) { Class<?> wrapClass = primitiveWrapperTypeMap.get(source[i]); if (wrapClass != null) { source[i] = wrapClass; } } } /////////// 杂项 ///////// /** * From Spring, 按顺序获取默认ClassLoader * * 1. Thread.currentThread().getContextClassLoader() * * 2. ClassUtil的加载ClassLoader * * 3. SystemClassLoader */ public static ClassLoader getDefaultClassLoader() { ClassLoader cl = null; try { cl = Thread.currentThread().getContextClassLoader(); } catch (Throwable ex) { // Cannot access thread context ClassLoader - falling back... } if (cl == null) { // No thread context class loader -> use class loader of this class. cl = ClassUtils.class.getClassLoader(); if (cl == null) { // getClassLoader() returning null indicates the bootstrap ClassLoader try { cl = ClassLoader.getSystemClassLoader(); } catch (Throwable ex) { // Cannot access system ClassLoader - oh well, maybe the caller can live with null... } } } return cl; } /** * 获取CGLib处理过后的实体的原Class. */ public static Class<?> unwrapCglib(Object instance) { Validate.notNull(instance, "Instance must not be null"); Class<?> clazz = instance.getClass(); if ((clazz != null) && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) { Class<?> superClass = clazz.getSuperclass(); if ((superClass != null) && !Object.class.equals(superClass)) { return superClass; } } return clazz; } /** * 通过反射, 获得Class定义中声明的泛型参数的类型, * * 注意泛型必须定义在父类处. 这是唯一可以通过反射从泛型获得Class实例的地方. * * 如无法找到, 返回Object.class. * * eg. public UserDao extends HibernateDao<User> * * @param clazz The class to introspect * @return the first generic declaration, or Object.class if cannot be determined */ public static <T> Class<T> getClassGenricType(final Class clazz) { return getClassGenricType(clazz, 0); } /** * 通过反射, 获得Class定义中声明的父类的泛型参数的类型. * * 注意泛型必须定义在父类处. 这是唯一可以通过反射从泛型获得Class实例的地方. * * 如无法找到, 返回Object.class. * * 如public UserDao extends HibernateDao<User,Long> * * @param clazz clazz The class to introspect * @param index the Index of the generic ddeclaration, start from 0. * @return the index generic declaration, or Object.class if cannot be determined */ public static Class getClassGenricType(final Class clazz, final int index) { Type genType = clazz.getGenericSuperclass(); if (!(genType instanceof ParameterizedType)) { logger.warn(clazz.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 " + clazz.getSimpleName() + "'s Parameterized Type: " + params.length); return Object.class; } if (!(params[index] instanceof Class)) { logger.warn(clazz.getSimpleName() + " not set the actual class on superclass generic parameter"); return Object.class; } return (Class) params[index]; } /** * 探测类是否存在classpath中 */ public static boolean isPresent(String className, ClassLoader classLoader) { try { classLoader.loadClass(className); return true; } catch (Throwable ex) { // Class or one of its dependencies is not present... return false; } } }