spring AopUtils分析

AopUtils是spring aop中很常用的一个工具类,提供了许多通用方法:

一、isJdkDynamicProxy

public static boolean isJdkDynamicProxy(@Nullable Object object) {
    return (object instanceof SpringProxy && Proxy.isProxyClass(object.getClass()));
}

1)、方法描述:
判断当前对象是否是由JDK动态代理产生的代理对象
2)、执行逻辑:
1⃣️ 首先判断对象是否实现SpringProxy接口(注:spring产生的代理对象都会实现SpringProxy接口,具体原理可以参见:具体原理研究
2⃣️ 继而判断当前对象是否是JDK动态代理产生的代理对象。
只有当两者都满足的时候,才会返回true,表示该对象是spring JDK动态代理方式产生的代理对象。
3)、实现原理:
JDK动态代理产生的代理对象1⃣️会继承Proxy类,2⃣️已经产生的代理对象将会保存在proxyClassCache中,使用此方种式进行判断。(注:JDK动态代理产生的代理类都会有$Proxy前缀,笔者认为这里还可以根据类的名称进行判断,不过既然JDK的Proxy类已经提供了对应的功能,我们也不必要再造轮子了。)

 public static boolean isProxyClass(Class<?> cl) {
      return Proxy.class.isAssignableFrom(cl) && proxyClassCache.containsValue(cl);
   }

二、isCglibProxy

public static boolean isCglibProxy(@Nullable Object object) {
    return (object instanceof SpringProxy && ClassUtils.isCglibProxy(object));
}

1)、方法描述:
判断当前对象是否是由CGLIB产生的代理对象
2)、执行逻辑:
1⃣️ 首先判断对象是否实现SpringProxy接口;
2⃣️ 继而使用ClassUtils.isCglibProxy方法判断当前对象是否是CGLIB产生的代理对象。
只有当两者都满足的时候,才会返回true,表示该对象是由CGLIB产生的代理对象。
3)、实现原理:
CGLIB产生的代理类名中会包含$$符号,使用此种方式进行判断,具体判断逻辑如下:

public static boolean isCglibProxy(Object object) {
    return isCglibProxyClass(object.getClass());
}

public static boolean isCglibProxyClass(@Nullable Class<?> clazz) {
    return (clazz != null && isCglibProxyClassName(clazz.getName()));
}
public static boolean isCglibProxyClassName(@Nullable String className) {
    return (className != null && className.contains(CGLIB_CLASS_SEPARATOR));
}

三、isAopProxy

public static boolean isAopProxy(@Nullable Object object) {
    return (object instanceof SpringProxy &&
            (Proxy.isProxyClass(object.getClass()) || ClassUtils.isCglibProxyClass(object.getClass())));
}

1)、方法描述:
判断当前对象是否是AOP代理对象
2)、执行逻辑:
1⃣️ 首先判断对象是否实现SpringProxy接口;
2⃣️ 继而使用如下代码判断当前对象是否是AOP代理对象。

(Proxy.isProxyClass(object.getClass()) || ClassUtils.isCglibProxyClass(object.getClass())

3)、实现原理:
代理对象无非两种,JDK动态代理产生的代理对象或者CGLIB产生的代理对象,这里进行了或运算,无论当前对象是JDK动态代理产生的代理对象,还是CGLIB产生的代理对象,只要满足其一,就代表当前对象是AOP代理对象。

四、isEqualsMethod

public static boolean isEqualsMethod(@Nullable Method method) {
    return ReflectionUtils.isEqualsMethod(method);
}

1)、方法功能:
判断当前方法是否是Equals方法。
… isHashCodeMethod、isToStringMethod也是如此,分别判断当前方法是否是HashCode、toString方法,在这里不再赘述。

五、canApply

//判断targetClass类是否匹配切点的切入条件,或者说判断pc切点能否应用在targetClass类上
public static boolean canApply(Pointcut pc, Class<?> targetClass) ;

具体实现如下所示:

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
        Assert.notNull(pc, "Pointcut must not be null");
        if (!pc.getClassFilter().matches(targetClass)) {
            return false;
        }

        MethodMatcher methodMatcher = pc.getMethodMatcher();
        if (methodMatcher == MethodMatcher.TRUE) {
            // No need to iterate the methods if we're matching any method anyway...
            return true;
        }

        IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
        if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
            introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
        }

        Set<Class<?>> classes = new LinkedHashSet<>();
        if (!Proxy.isProxyClass(targetClass)) {
            classes.add(ClassUtils.getUserClass(targetClass));
        }
        classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

        //判断类中的方法是否匹配切点函数
        for (Class<?> clazz : classes) {
            Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
            for (Method method : methods) {
                if (introductionAwareMethodMatcher != null ?
                        introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
                        methodMatcher.matches(method, targetClass)) {
                    return true;
                }
            }
        }

        return false;
    }

六、findAdvisorsThatCanApply

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) 

1)、方法描述:
根据candidateAdvisors,挑选出可以应用在clazz类上的Advisor集合。

if (candidateAdvisors.isEmpty()) {
    return candidateAdvisors;
    }
    List<Advisor> eligibleAdvisors = new ArrayList<>();
    for (Advisor candidate : candidateAdvisors) {
        if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
            eligibleAdvisors.add(candidate);
        }
    }
    boolean hasIntroductions = !eligibleAdvisors.isEmpty();
    for (Advisor candidate : candidateAdvisors) {
        if (candidate instanceof IntroductionAdvisor) {
            // already processed
            continue;
        }
        if (canApply(candidate, clazz, hasIntroductions)) {
            eligibleAdvisors.add(candidate);
        }
    }
    return eligibleAdvisors;

2)、实现原理:
通过上面的代码块,我们可以看到,该方法最终是通过调用canApply方法来判断对应的Advisor能否应用在目标clazz上。

七、invokeJoinpointUsingReflection

@Nullable
public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args)
        throws Throwable {
    ReflectionUtils.makeAccessible(method);
    return method.invoke(target, args);
    ...	
}

1)、方法描述:
使用反射调用目标方法。
2)、执行过程:
1⃣️首先调用了ReflectionUtils.makeAccessible(method),相当于method.setAccsessible(true),避免了反射调用过程中的安全检查。
2⃣️执行反射调用。

    原文作者:Spring Boot
    原文地址: https://blog.csdn.net/wt_better/article/details/84791590
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞