Spring AOP 是基于什么技术实现的?

在这里插入图片描述

Spring AOP 主要基于 动态代理 (Dynamic Proxy) 技术实现。

它不会修改你的源代码(.java 文件),也不会在编译时修改字节码(.class 文件),而是在应用程序运行时,动态地为你需要增强的对象创建一个“代理”对象。我们最终调用和交互的,就是这个代理对象。

具体来说,Spring AOP 会根据情况自动选择以下两种动态代理技术中的一种:


1. JDK 动态代理 (JDK Dynamic Proxy)

这是 Java 官方提供的代理技术。

  • 实现方式:利用 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口。
  • 工作前提目标对象必须实现至少一个接口。
  • 工作原理:Spring AOP 会在运行时创建一个新的代理类,这个代理类实现了目标对象所实现的所有接口。当你调用代理对象的任何方法时,这个调用会被转发到 InvocationHandlerinvoke 方法中。在这个 invoke 方法里,Spring AOP 框架就有机会织入你的切面逻辑(比如执行 @Before 通知),然后再通过反射调用你原始目标对象的真正方法。

简单来说: 如果你的 UserServiceImpl 实现了 UserService 接口,Spring 就会创建一个代理对象,这个代理对象也实现了 UserService 接口,它内部“包裹”着你真正的 UserServiceImpl 实例。

2. CGLIB (Code Generation Library)

这是一个强大的、高性能的第三方代码生成库。

  • 实现方式:通过字节码增强 (Bytecode Enhancement) 技术。
  • 工作前提:目标对象不需要实现接口
  • 工作原理:CGLIB 会在运行时动态地创建一个目标对象的子类作为代理对象。然后,它会重写 (Override) 目标类中所有可以被重写的方法(即非 final 的方法)。在这些重写的代理方法中,它会织入你的切面逻辑,然后再通过调用 super.method() 去执行原始父类(也就是你的目标对象)的业务逻辑。

简单来说: 如果你的 OrderService 类没有实现任何接口,Spring 就会利用 CGLIB 创建一个 OrderService 的子类(例如 OrderService$$EnhancerBySpringCGLIB)作为代理。


Spring 如何选择?

这是一个常见的面试题:

  • 在老的 Spring 版本或传统配置中:如果目标对象实现了接口,默认使用 JDK 动态代理;如果目标对象没有实现接口,则使用 CGLIB
  • 在现代的 Spring Boot (2.x 及以后) 中:为了解决类内部方法调用AOP失效等问题并统一行为,默认统一使用 CGLIB,无论你的类是否实现了接口。当然,你也可以通过配置 spring.aop.proxy-target-class=false 来强制在有接口的情况下使用 JDK 动态代理。

总结表格

特性JDK 动态代理CGLIB
核心技术Java 反射字节码增强
代理方式实现目标对象的接口继承目标对象,创建其子类
前提条件目标对象必须实现接口目标对象不能是 final 类,方法不能是 final
Spring Boot 默认是 (推荐)

总结:
Spring AOP 的魔法在于运行时动态代理。它通过 JDK 动态代理(基于接口)或 CGLIB(基于继承)来创建一个“包装”你原始对象的代理,并在这个代理中神不知鬼不觉地织入了你的横切逻辑,而这一切都无需你修改任何一行业务代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

冰糖心书房

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

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

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

打赏作者

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

抵扣说明:

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

余额充值