14jdk 和 cglib 在 Spring 中的统一

adviso结构类图

Spring 中对切点、通知、切面的抽象如下

  • 切点:接口 Pointcut,典型实现 AspectJExpressionPointcut

  • 通知:典型接口为 MethodInterceptor 代表环绕通知

  • 切面:Advisor,包含一个 Advice 通知,PointcutAdvisor 包含一个 Advice 通知和一个 Pointcut

  • 代理相关类图

    • AopProxyFactory 根据 proxyTargetClass 等设置选择 AopProxy 实现

    • AopProxy 通过 getProxy 创建代理对象

    • 图中 Proxy 都实现了 Advised 接口,能够获得关联的切面集合与目标(其实是从 ProxyFactory 取得)

    • 调用代理方法时,会借助 ProxyFactory 将通知统一转为环绕通知:MethodInterceptor

adviso增强实现

  1. 底层的切点实现

  2. 底层的通知实现

  3. 底层的切面实现

  4. ProxyFactory 用来创建代理

    • 如果指定了接口,且 proxyTargetClass = false,使用 JdkDynamicAopProxy

    • 如果没有指定接口,或者 proxyTargetClass = true,使用 ObjenesisCglibAopProxy

      • 例外:如果目标是接口类型或已经是 Jdk 代理,使用 JdkDynamicAopProxy

package com.butch.a15;

import com.butch.a13.Target;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;

public class A15 {

    //切面类
    @Aspect
    static class MyAspect{
        //通知
        @Before("execution(* foo())")//切点
        public void before(){
            System.out.println("==========前置增强=======");
        }
        @Before("execution(* foo())")
        public void after(){
            System.out.println("==========后置增强=======");
        }
    }

    public static void main(String[] args) {

        /*
            两个切面概念
            aspect =
                通知1(advice) +  切点1(pointcut)
                通知2(advice) +  切点2(pointcut)
                通知3(advice) +  切点3(pointcut)
                ...
            advisor = 更细粒度的切面,包含一个通知和切点 最终生效 aspect拆解为多个advisor
         */

        //advisor切点
        AspectJExpressionPointcut aspectJExpressionPointcut = new AspectJExpressionPointcut();
        aspectJExpressionPointcut.setExpression("execution(* foo())");
        
        //advisor通知
        MethodInterceptor advice = new MethodInterceptor() {
            @Override
            public Object invoke(MethodInvocation methodInvocation) throws Throwable {
                System.out.println("==========before");
                Object res = methodInvocation.proceed();
                System.out.println("=============after");
                return res;
            }
        };
        
        //advisor漆面
        DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(aspectJExpressionPointcut, advice);

        //创建代理
        ProxyFactory proxyFactory = new ProxyFactory();
        Target1 target1 = new Target1();
        proxyFactory.setTarget(target1);
        proxyFactory.addAdvisor(advisor);
        //设置实现的接口
        proxyFactory.setInterfaces(I1.class);
        proxyFactory.setProxyTargetClass(true);
        I1 proxy = (I1) proxyFactory.getProxy();
        System.out.println("proxy.getClass() = " + proxy.getClass());
        proxy.bar();
        proxy.foo();

    }


    interface I1 {
        void foo();

        void bar();
    }

    static class Target1 implements I1 {
        public void foo() {
            System.out.println("target1 foo");
        }

        public void bar() {
            System.out.println("target1 bar");
        }
    }

    static class Target2 {
        public void foo() {
            System.out.println("target2 foo");
        }

        public void bar() {
            System.out.println("target2 bar");
        }
    }
}

spring代理选择规则

a. proxyTargetClass = false, 目标实现了接口, 用 jdk 实现

b. proxyTargetClass = false, 目标没有实现接口, 用 cglib 实现

c. proxyTargetClass = true, 总是使用 cglib 实现

切点匹配

模拟AOP在进行切点匹配的逻辑

package com.butch.a16;

import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.StaticMethodMatcherPointcut;
import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Method;

public class A16 {
    public static void main(String[] args) throws NoSuchMethodException {
//        AspectJExpressionPointcut pt1 = new AspectJExpressionPointcut();
//        pt1.setExpression("execution(* bar())");
//        System.out.println("pt1.matches(T1.class.getMethod(\"bar\"),T1.class) = " + pt1.matches(T1.class.getMethod("bar"), T1.class)); //true
//        System.out.println("pt1.matches(T1.class.getMethod(\"bar\"),T1.class) = " + pt1.matches(T1.class.getMethod("foo"), T1.class)); //false
//
//        AspectJExpressionPointcut pt2 = new AspectJExpressionPointcut();
//        pt2.setExpression("@annotation(org.springframework.transaction.annotation.Transactional)");
//        System.out.println("pt2.matches(T1.class.getMethod(\"bar\"),T1.class) = " + pt2.matches(T1.class.getMethod("bar"), T1.class)); //true
//        System.out.println("pt2.matches(T1.class.getMethod(\"bar\"),T1.class) = " + pt2.matches(T1.class.getMethod("foo"), T1.class)); //false

        //处理类似上或者接口上注解的匹配
        StaticMethodMatcherPointcut pt3 = new StaticMethodMatcherPointcut() {
            @Override
            public boolean matches(Method method, Class<?> aClass) {
                //优先匹配方法上的
                MergedAnnotations from = MergedAnnotations.from(method);
                if (from.isPresent(Transactional.class)){
                    return true;
                }
                //匹配类上的注解,默认在本类寻找,加入TYPE_HIERARCHY在父类和父接口寻找
                MergedAnnotations from1 = MergedAnnotations.from(aClass, MergedAnnotations.SearchStrategy.TYPE_HIERARCHY);
                if (from1.isPresent(Transactional.class)){
                    return true;
                }
                return false;
            }
        };
        System.out.println("pt3.matches(T1.class.getMethod(\"foo\"),T1.class) = " + pt3.matches(T1.class.getMethod("foo"), T1.class));
        System.out.println("pt3.matches(T1.class.getMethod(\"foo\"),T1.class) = " + pt3.matches(T1.class.getMethod("bar"), T1.class));
        System.out.println("pt3.matches(T1.class.getMethod(\"foo\"),T1.class) = " + pt3.matches(T2.class.getMethod("foo"), T2.class));
        System.out.println("pt3.matches(T1.class.getMethod(\"foo\"),T1.class) = " + pt3.matches(T3.class.getMethod("foo"), T3.class));

    }


    static class T1 {
        @Transactional
        public void foo() {
        }
        public void bar() {
        }
    }

    @Transactional
    static class T2 {
        public void foo() {
        }
    }

    @Transactional
    interface I3 {
        void foo();
    }
    static class T3 implements I3 {
        public void foo() {
        }
    }
}

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值