Spring AOP 支持哪两种动态代理方式(最新推荐)

 更新时间:2025年06月27日 10:09:17   作者:冰糖心书房  
动态代理在运行时创建目标对象的增强代理,Spring AOP支持JDK代理(基于接口)和CGLIB代理(基于继承),Spring Boot默认使用CGLIB解决方法自调用问题,也可通过配置切换代理方式,本文给大家介绍Spring AOP支持哪两种动态代理方式,感兴趣的朋友一起看看吧

什么是动态代理?

动态代理就是,在程序运行期,创建目标对象的代理对象,并对目标对象中的方法进行功能性增强的一种技术。

在生成代理对象的过程中,目标对象不变,代理对象中的方法是目标对象方法的增强方法。可以理解为运行期间,对象中方法的动态拦截,在拦截方法的前后执行功能操作。

Spring AOP 支持以下两种动态代理方式:

  1. JDK 动态代理 (JDK Dynamic Proxy)
  2. CGLIB 代理 (Code Generation Library)

Spring 框架会根据你的业务对象(目标对象)的情况,智能地选择其中一种来创建代理。

1. JDK 动态代理

  • 技术基础:Java 官方提供的 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口,是 Java 原生支持的。
  • 实现方式:在运行时,创建一个新的代理类,这个代理类会实现目标对象所实现的所有接口
  • 硬性要求被代理的目标对象必须实现至少一个接口。 如果一个类没有实现任何接口,JDK 动态代理就无法为其创建代理。
  • 工作流程:当你调用代理对象的方法时,这个调用会被转发到 InvocationHandlerinvoke() 方法中。Spring AOP 在 invoke() 方法内部织入了你的切面逻辑(如 @Before@After 等),然后再通过 Java 的反射机制调用原始目标对象的方法。

2. CGLIB 代理

  • 技术基础:一个强大的第三方代码生成库(Spring 内部集成了它),它通过字节码增强 (Bytecode Enhancement) 技术来工作。
  • 实现方式:在运行时,动态地创建一个被代理对象的子类作为代理对象。
  • 硬性要求:被代理的目标类不能是 final 类,需要被代理的方法也不能是 finalprivate,因为子类无法继承 final 类或重写 final/private 方法。
  • 工作流程:代理类会重写(Override)父类(即你的目标对象)中所有非 final 的方法。在这些重写的方法里,Spring AOP 织入了切面逻辑,然后再通过调用 super.method() 来执行原始目标对象的业务逻辑。

Spring 如何选择?

这是面试中的高频问题,因为这个默认行为在不同版本中有所变化。

场景Spring 的选择
目标对象实现了接口老的 Spring 版本传统 Spring XML 配置中,默认使用 JDK 动态代理

Spring Boot (2.x 及以后) 中,为了统一行为和解决一些代理问题,默认依然使用 CGLIB
目标对象没有实现接口无论在哪个版本,都只能使用 CGLIB

为什么 Spring Boot 默认使用 CGLIB?
主要原因是为了解决“方法自调用时 AOP 失效”的问题,并提供更一致的行为。使用 CGLIB 可以确保即使目标对象实现了接口,代理的也是类本身,这在处理一些复杂的依赖注入和内部调用场景时更加可靠。

当然,你也可以通过在 application.properties 中进行配置来改变这个默认行为:

# 如果设置为 true (默认值),则统一使用 CGLIB
# 如果设置为 false,则在目标对象实现接口时,会优先使用 JDK 动态代理
spring.aop.proxy-target-class=true 

总结对比

特性JDK 动态代理CGLIB 代理
代理方式基于接口 (实现共同接口)基于继承 (创建子类)
前提条件目标对象必须实现接口目标对象不能是 final 类
性能在早期版本中,通过反射调用性能略低于 CGLIB。但在目前JDK 版本中,两者性能差距已经非常小。性能通常被认为略高,因为它直接操作字节码并调用 super
Spring Boot 默认

到此这篇关于Spring AOP 支持哪两种动态代理方式?的文章就介绍到这了,更多相关spring aop动态代理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 强烈推荐 5 款好用的REST API工具(收藏)

    强烈推荐 5 款好用的REST API工具(收藏)

    市面上可用的 REST API 工具选项有很多,我们来看看其中一些开发人员最喜欢的工具。本文通过图文实例代码相结合给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2020-12-12
  • java构建Stream流的多种方式总结

    java构建Stream流的多种方式总结

    Java 8引入了Stream流作为一项新的特性,它是用来处理集合数据的一种函数式编程方式,本文为大家整理了多种java构建Stream流的方式,希望对大家有所帮助
    2023-11-11
  • Spring boot调用Oracle存储过程的两种方式及完整代码

    Spring boot调用Oracle存储过程的两种方式及完整代码

    这篇文章主要给大家介绍了关于Spring boot调用Oracle存储过程的两种方式及完整代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2020-08-08
  • Mybatis pagehelper分页插件使用过程解析

    Mybatis pagehelper分页插件使用过程解析

    这篇文章主要介绍了mybatis pagehelper分页插件使用过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • java实现网页验证码功能

    java实现网页验证码功能

    这篇文章主要为大家详细介绍了java实现网页验证码功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-10-10
  • Spring Security 过滤器注册脉络梳理

    Spring Security 过滤器注册脉络梳理

    这篇文章主要介绍了Spring Security过滤器注册脉络梳理,Spring Security在Servlet的过滤链中注册了一个过滤器FilterChainProxy,它会把请求代理到Spring Security自己维护的多个过滤链,每个过滤链会匹配一些URL,如果匹配则执行对应的过滤器
    2022-08-08
  • Java自然排序Comparable使用方法解析

    Java自然排序Comparable使用方法解析

    这篇文章主要介绍了Java自然排序Comparable使用方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04
  • 微信小程序与Java后端接口交互

    微信小程序与Java后端接口交互

    本文主要介绍了微信小程序与Java后端接口交互,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • 浅谈java多线程 join方法以及优先级方法

    浅谈java多线程 join方法以及优先级方法

    下面小编就为大家带来一篇浅谈java多线程 join方法以及优先级方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-01-01
  • Spring事务失效之常见场景分析

    Spring事务失效之常见场景分析

    这篇文章主要介绍了Spring事务失效之常见场景,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04

最新评论