Spring 是如何将 Advice 织入到目标对象中的?

Spring AOP 将 Advice(通知)织入到目标对象的过程,主要依赖于动态代理技术(JDK 动态代理或 CGLIB 动态代理)。下面分别介绍这两种代理方式下,Spring 如何织入 Advice:

1. JDK 动态代理:

  • 条件: 目标对象必须实现至少一个接口。

  • 原理:

    • Spring 使用 java.lang.reflect.Proxy 类创建代理对象。
    • 代理对象实现了与目标对象相同的接口。
    • 代理对象持有一个 java.lang.reflect.InvocationHandler 接口的实现类(通常是 Spring 提供的 JdkDynamicAopProxy)的引用。
    • 当客户端调用代理对象的方法时,实际上会调用 InvocationHandlerinvoke() 方法。
    • invoke() 方法负责:
      1. 根据配置的通知类型(前置通知、后置通知、环绕通知等),在调用目标方法前后执行相应的通知逻辑。
      2. 通过反射调用目标对象的真实方法。
  • 织入过程:

    1. 创建 InvocationHandler Spring 根据切面(Aspect)和通知(Advice)配置,创建一个 InvocationHandler 的实现类(JdkDynamicAopProxy)。
    2. 创建代理对象: Spring 使用 Proxy.newProxyInstance() 方法创建代理对象,传入类加载器、目标对象实现的接口数组、以及 InvocationHandler 实例。
    3. 方法调用: 当客户端调用代理对象的方法时,会触发 InvocationHandlerinvoke() 方法。
    4. 执行通知: invoke() 方法根据配置的通知类型,在调用目标方法前后执行相应的通知逻辑。
      • 前置通知(Before Advice): 在调用目标方法之前执行。
      • 后置通知(After Advice): 在调用目标方法之后执行(无论是否发生异常)。
      • 返回通知(After Returning Advice): 在目标方法成功返回后执行。
      • 异常通知(After Throwing Advice): 在目标方法抛出异常后执行。
      • 环绕通知(Around Advice): 包裹目标方法,可以在目标方法执行前后执行自定义逻辑,甚至可以阻止目标方法的执行。
    5. 调用目标方法: invoke() 方法通过反射调用目标对象的真实方法。
    6. 返回结果: 将目标方法的返回值(如果有)返回给客户端。

2. CGLIB 动态代理:

  • 条件: 目标对象不需要实现接口。

  • 原理:

    • Spring 使用 CGLIB 库创建代理对象。
    • 代理对象是目标对象的子类。
    • 代理对象重写了目标对象的所有非 final 方法。
    • 在重写的方法中,Spring 会根据配置的通知类型,在调用父类(即目标对象)的方法前后,插入相应的通知逻辑。
    • CGLIB 使用 ASM 字节码操作框架来生成子类。
  • 织入过程:

    1. 创建 MethodInterceptor: Spring根据切面和通知, 会创建一个MethodInterceptor
    2. 创建代理对象: Spring 使用 CGLIB 的 Enhancer 类创建代理对象,设置父类为目标类,设置 Callback 为MethodInterceptor
    3. 方法调用: 当客户端调用代理对象的方法时,会触发 MethodInterceptorintercept 方法。
    4. 执行通知: intercept 方法根据配置的通知类型,在调用目标方法前后执行相应的通知逻辑。
      • 通知类型与 JDK 动态代理相同(前置、后置、返回、异常、环绕)。
    5. 调用目标方法: 通过调用父类(即目标对象)的相应方法。
    6. 返回结果: 将目标方法的返回值(如果有)返回给客户端。

总结:

Spring AOP 通过动态代理技术将 Advice 织入到目标对象中。

  • JDK 动态代理: 基于接口,通过 InvocationHandler 在目标方法调用前后执行通知。
  • CGLIB 动态代理: 基于类,通过生成目标类的子类,在子类方法中调用父类方法前后执行通知。

无论是 JDK 动态代理还是 CGLIB 动态代理,Spring AOP 的核心思想都是:在不修改目标对象源代码的情况下,通过代理对象来增强目标对象的功能,实现横切关注点的模块化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰糖心书房

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值