spring工具类 abstract class ReflectionUtils

版权声明:欢迎交流、沟通 QQ:983433479 微信:wj983433479 ;努力学习~赚钱养家不是梦。 https://blog.csdn.net/u012881904/article/details/80015012

spring工具类 abstract class ReflectionUtils

使用反射API的简单实用程序类和处理异常处理

这里写图片描述

为何看这个

在看@EnableScheduling中对于类中方法的查找所有的注解的时候看到啦,如此的简介,内部提供了很多的相同的封装,首先从这个反射的处理类开始下手spring task 通过@EnableScheduling启动流程简析

成员变量

这里写图片描述
Java中的四种引用类型 Strong, Soft, Weak And Phantom
ConcurrentReferenceHashMap 使用Soft or Weak 类型的引用,加快查找类的方法和类的成员变量目的就是:to avoid the JVM’s SecurityManager check and defensive array copying(还有就是避免JVM的安全性检测和防御性拷贝)
A {@link ConcurrentHashMap} that uses {@link ReferenceType#SOFT soft} or @linkplain ReferenceType#WEAK weak} references for both {@code keys} and {@code values}. This class can be used as an alternative to {@code Collections.synchronizedMap(new WeakHashMap

Class.java 
public Method[] getDeclaredMethods() throws SecurityException {
    checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
    return copyMethods(privateGetDeclaredMethods(false));
}
private static Method[] copyMethods(Method[] arg) {
    Method[] out = new Method[arg.length];
    ReflectionFactory fact = getReflectionFactory();
    for (int i = 0; i < arg.length; i++) {
        out[i] = fact.copyMethod(arg[i]);
    }
    return out;
}

成员变量:

/**
 * Naming prefix for CGLIB-renamed methods.
 * @see #isCglibRenamedMethod
 */
private static final String CGLIB_RENAMED_METHOD_PREFIX = "CGLIB$";

private static final Method[] NO_METHODS = {};

private static final Field[] NO_FIELDS = {};


/**
 * Cache for {@link Class#getDeclaredMethods()} plus equivalent default methods
 * from Java 8 based interfaces, allowing for fast iteration.
 */
private static final Map<Class< ?>, Method[]> declaredMethodsCache =
        new ConcurrentReferenceHashMap<Class<?>, Method[]>(256);

/**
 * Cache for {@link Class#getDeclaredFields()}, allowing for fast iteration.
 */
private static final Map<Class< ?>, Field[]> declaredFieldsCache =
        new ConcurrentReferenceHashMap<Class< ?>, Field[]>(256);

Filed

这里写图片描述

findField

从当前类开始查找,遍历所有的父类,直到找到相同的成员变量

public static Field findField(Class< ?> clazz, String name, Class< ?> type) {
        Class< ?> searchType = clazz;
        while (Object.class != searchType && searchType != null) {
           // 找到当前类所有的Filed
            Field[] fields = getDeclaredFields(searchType);
            for (Field field : fields) {
                if ((name == null || name.equals(field.getName())) &&
                        (type == null || type.equals(field.getType()))) {
                    return field;
                }
            }
            searchType = searchType.getSuperclass();
        }
        return null;
    }
getDeclaredFields

从当前class中获取定义的成员变量,缓存的目的是由于clazz.getDeclaredFields()的实现会防御性的进行拷贝。in order to avoid the JVM’s SecurityManager check and defensive array copying.

private static Field[] getDeclaredFields(Class< ?> clazz) {
        Field[] result = declaredFieldsCache.get(clazz);
        if (result == null) {
            result = clazz.getDeclaredFields();
            declaredFieldsCache.put(clazz, (result.length == 0 ? NO_FIELDS : result));
        }
        return result;
    }

makeAccessible

处理可访问性,类似的还有方法、构造,封装了对于反射中经常看到的可访问性的操作

    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);
        }
    }
    public static void makeAccessible(Method method) {
        if ((!Modifier.isPublic(method.getModifiers()) ||
                !Modifier.isPublic(method.getDeclaringClass().getModifiers())) && !method.isAccessible()) {
            method.setAccessible(true);
        }
    }
    public static void makeAccessible(Constructor< ?> ctor) {
        if ((!Modifier.isPublic(ctor.getModifiers()) ||
                !Modifier.isPublic(ctor.getDeclaringClass().getModifiers())) && !ctor.isAccessible()) {
            ctor.setAccessible(true);
        }
    }   

doWithFields

进行回调操作运行过滤处理Filed

public static void doWithFields(Class< ?> clazz, FieldCallback fc, FieldFilter ff) {
        // Keep backing up the inheritance hierarchy.
        Class< ?> targetClass = clazz;
        do {
            Field[] fields = getDeclaredFields(targetClass);//当前类中的Filed
            for (Field field : fields) {
                // 匹配过滤
                if (ff != null && !ff.matches(field)) {
                    continue;
                }
                try {
                    fc.doWith(field);//回调
                }
                catch (IllegalAccessException ex) {
                    throw new IllegalStateException("Not allowed to access field '" + field.getName() + "': " + ex);
                }
            }
            // 查找父类中的Filed
            targetClass = targetClass.getSuperclass();
        }
        while (targetClass != null && targetClass != Object.class);
    }

method

这里写图片描述

Method findMethod

查找当前类中类或者父类或者接口中默认实现的方法,先比较当前类->接口默认实现-父类

public static Method findMethod(Class< ?> clazz, String name, Class< ?>... paramTypes) {
        Class< ?> searchType = clazz;
        while (searchType != null) {
            Method[] methods = (searchType.isInterface() ? searchType.getMethods() : getDeclaredMethods(searchType));
            for (Method method : methods) {
                if (name.equals(method.getName()) &&
                        (paramTypes == null || Arrays.equals(paramTypes, method.getParameterTypes()))) {
                    return method;
                }
            }
            // 查找父类
            searchType = searchType.getSuperclass();
        }
        return null;
    }

getDeclaredMethods

获取当前类或者Java8 接口的默认实现的方法

private static Method[] getDeclaredMethods(Class< ?> clazz) {

        Method[] result = declaredMethodsCache.get(clazz);
        if (result == null) {
            Method[] declaredMethods = clazz.getDeclaredMethods();
            List<Method> defaultMethods = findConcreteMethodsOnInterfaces(clazz);
            // 从接口中找到默认的实现
            if (defaultMethods != null) {
                result = new Method[declaredMethods.length + defaultMethods.size()];
                System.arraycopy(declaredMethods, 0, result, 0, declaredMethods.length);
                int index = declaredMethods.length;
                for (Method defaultMethod : defaultMethods) {
                    result[index] = defaultMethod;
                    index++;
                }
            }
            else {
                result = declaredMethods;
            }
            declaredMethodsCache.put(clazz, (result.length == 0 ? NO_METHODS : result));
        }
        return result;
    }

findConcreteMethodsOnInterfaces

des Java 8 default methods from locally implemented interfaces,找到接口中默认实现的方法,其实就是找到非抽象的方法

private static List<Method> findConcreteMethodsOnInterfaces(Class< ?> clazz) {
        List<Method> result = null;
        for (Class< ?> ifc : clazz.getInterfaces()) {
            for (Method ifcMethod : ifc.getMethods()) {
                //当前的方法不是抽象的方法就有默认的实现
                if (!Modifier.isAbstract(ifcMethod.getModifiers())) {
                    if (result == null) {
                        result = new LinkedList<Method>();
                    }
                    result.add(ifcMethod);
                }
            }
        }
        return result;
    }

doWithLocalMethods

类似找到当前类或者接口中的所有的方法,然后进行回调操作

    public static void doWithLocalMethods(Class< ?> clazz, MethodCallback mc) {
        Method[] methods = getDeclaredMethods(clazz);
        for (Method method : methods) {
            try {
                mc.doWith(method);
            }
            catch (IllegalAccessException ex) {
                throw new IllegalStateException("Not allowed to access method '" + method.getName() + "': " + ex);
            }
        }
    }

doWithMethods

这里是级联的回调,处理本身之外还要对于父类进行回调.Perform the given callback operation on all matching methods of the given class and superclasses (or given interface and super-interfaces 这里可能会添加重复的默认实现的方法,可以使用过滤处理).
可能会出现重复的方法The same named method occurring on subclass and superclass will appear twice, unless excluded by the specified {@link MethodFilter}.

public static void doWithMethods(Class< ?> clazz, MethodCallback mc, MethodFilter mf) {
        // Keep backing up the inheritance hierarchy.
        Method[] methods = getDeclaredMethods(clazz);
        for (Method method : methods) {
            if (mf != null && !mf.matches(method)) {
                continue;
            }
            try {
                mc.doWith(method); //处理回调
            }
            catch (IllegalAccessException ex) {
                throw new IllegalStateException("Not allowed to access method '" + method.getName() + "': " + ex);
            }
        }
        if (clazz.getSuperclass() != null) {
            doWithMethods(clazz.getSuperclass(), mc, mf);
        }
        else if (clazz.isInterface()) {
            for (Class< ?> superIfc : clazz.getInterfaces()) {
                doWithMethods(superIfc, mc, mf);
            }
        }
    }

getUniqueDeclaredMethods

找到当前类的父类、接口默认实现等等,但是当前不存在重复的方法Get the unique set of declared methods on the leaf class and all superclasses. Leaf class methods are included first and while traversing the superclass hierarchy any methods found with signatures matching a method already included are filtered out.

public static Method[] getUniqueDeclaredMethods(Class< ?> leafClass) {
        final List<Method> methods = new ArrayList<Method>(32);
        doWithMethods(leafClass, new MethodCallback() {
            @Override
            public void doWith(Method method) {
                boolean knownSignature = false;
                Method methodBeingOverriddenWithCovariantReturnType = null;
                for (Method existingMethod : methods) {
                    if (method.getName().equals(existingMethod.getName()) &&
                            Arrays.equals(method.getParameterTypes(), existingMethod.getParameterTypes())) {
                        // Is this a covariant return type situation?
                        if (existingMethod.getReturnType() != method.getReturnType() &&
                                existingMethod.getReturnType().isAssignableFrom(method.getReturnType())) {
                            methodBeingOverriddenWithCovariantReturnType = existingMethod;
                        }
                        else {
                            knownSignature = true;
                        }
                        break;
                    }
                }
                if (methodBeingOverriddenWithCovariantReturnType != null) {
                    methods.remove(methodBeingOverriddenWithCovariantReturnType);
                }
                if (!knownSignature && !isCglibRenamedMethod(method)) {
                    methods.add(method);
                }
            }
        });
        return methods.toArray(new Method[methods.size()]);
    }

getAllDeclaredMethods(Class

public static Method[] getAllDeclaredMethods(Class< ?> leafClass) {
        final List<Method> methods = new ArrayList<Method>(32);
        doWithMethods(leafClass, new MethodCallback() {
            @Override
            public void doWith(Method method) {
                methods.add(method);
            }
        });
        return methods.toArray(new Method[methods.size()]);
    }

invokeMethod

调用方法,添加异常处理

public static Object invokeMethod(Method method, Object target, Object... args) {
        try {
            return method.invoke(target, args);
        }
        catch (Exception ex) {
            handleReflectionException(ex);
        }
        throw new IllegalStateException("Should never get here");
    }

异常处理(对于反射异常重新封装)

这里写图片描述
方便查看和理解

public static void handleReflectionException(Exception ex) {
        if (ex instanceof NoSuchMethodException) {
            throw new IllegalStateException("Method not found: " + ex.getMessage());
        }
        if (ex instanceof IllegalAccessException) {
            throw new IllegalStateException("Could not access method: " + ex.getMessage());
        }
        if (ex instanceof InvocationTargetException) {
            handleInvocationTargetException((InvocationTargetException) ex);
        }
        if (ex instanceof RuntimeException) {
            throw (RuntimeException) ex;
        }
        throw new UndeclaredThrowableException(ex);
    }

public static void handleInvocationTargetException(InvocationTargetException ex) {
        rethrowRuntimeException(ex.getTargetException());
    }

public static void rethrowRuntimeException(Throwable ex) {
        if (ex instanceof RuntimeException) {
            throw (RuntimeException) ex;
        }
        if (ex instanceof Error) {
            throw (Error) ex;
        }
        throw new UndeclaredThrowableException(ex);
    }
public static void rethrowException(Throwable ex) throws Exception {
    if (ex instanceof Exception) {
        throw (Exception) ex;
    }
    if (ex instanceof Error) {
        throw (Error) ex;
    }
    throw new UndeclaredThrowableException(ex);
}

回调过滤处理,方便根据业务进行处理(内部接口)

这里写图片描述
回调处理,对于桥接方法没有接触过:什么时候会生成桥接方法?就是说一个子类在继承(或实现)一个父类(或接口)的泛型方法时,在子类中明确指定了泛型类型,那么在编译时编译器会自动生成桥接方法,兼容早期的版本。具体了解可以参考下面的博客
jclasslib Bytecode viewer-IDEA 插件
java中什么是bridge method(桥接方法)
Java系列:关于Java中的桥接方法
spring 中 BridgeMethodResolver也有类似的处理

public interface MethodCallback {

        /**
         * Perform an operation using the given method.
         * @param method the method to operate on
         */
        void doWith(Method method);
    }
public interface MethodFilter {

    /**
     * Determine whether the given method matches.
     * @param method the method to check
     * 过滤不需要回调的方法
     */
    boolean matches(Method method);
}
/**
 * Pre-built MethodFilter that matches all non-bridge methods.
 */
public static final MethodFilter NON_BRIDGED_METHODS = new MethodFilter() {

    @Override
    public boolean matches(Method method) {
        return !method.isBridge();
    }
};
/**
 * 去掉桥接和Object自身的方法
 * Pre-built MethodFilter that matches all non-bridge methods
 * which are not declared on {@code java.lang.Object}.
 */
public static final MethodFilter USER_DECLARED_METHODS = new MethodFilter() {

    @Override
    public boolean matches(Method method) {
        return (!method.isBridge() && method.getDeclaringClass() != Object.class);
    }
};

判断性方法

这里写图片描述

/**
     * Determine whether the given method is a CGLIB 'renamed' method,
     * following the pattern "CGLIB$methodName$0".
     * @param renamedMethod the method to check
     * @see org.springframework.cglib.proxy.Enhancer#rename
     */
    public static boolean isCglibRenamedMethod(Method renamedMethod) {
        String name = renamedMethod.getName();
        if (name.startsWith(CGLIB_RENAMED_METHOD_PREFIX)) {
            int i = name.length() - 1;
            while (i >= 0 && Character.isDigit(name.charAt(i))) {
                i--;
            }
            return ((i > CGLIB_RENAMED_METHOD_PREFIX.length()) &&
                        (i < name.length() - 1) && name.charAt(i) == '$');
        }
        return false;
    }
public static boolean isPublicStaticFinal(Field field) {
        int modifiers = field.getModifiers();
        return (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers));
    }

总结

多看看优秀的代码,莫要重复创造轮子,同时学习一些没有了解的知识。

猜你喜欢

转载自blog.csdn.net/u012881904/article/details/80015012