spring AopUtils分析

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】
免费领取10G资料包与项目实战视频资料

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⃣️执行反射调用。


来源:[]()

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » spring AopUtils分析

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏