cglib能为无接口类加切面,因其通过asm生成目标类非final子类并重写方法插入拦截逻辑,绕过接口依赖;相比jdk代理的反射调用,它调用链更短、性能更优,spring默认采用以降低抽象负担。

CGLIB继承代理能直接为没接口的普通类加切面,根本原因在于它不依赖接口契约,而是靠字节码层面生成子类来接管方法调用。
绕过接口限制是核心前提
JDK动态代理必须基于接口——它生成的代理类实现的是目标类的接口,而非目标类本身。如果一个类没实现任何接口,Proxy.newProxyInstance连编译都过不去。CGLIB不走这条路,它用ASM在运行时生成目标类的子类,只要目标类不是final,就能被继承、被重写,自然也就没有“必须有接口”这一门槛。
增强逻辑通过方法重写落地
CGLIB代理的本质,是在子类中重写目标类所有非final方法,并在重写体里插入拦截器(MethodInterceptor)逻辑。比如原始类有个submit()方法,代理子类就覆写submit(),在super.submit()前后塞入日志、事务等切面代码。这种方式天然适配类结构,不需要提前约定方法签名,也不受接口定义范围约束。
调用链更短,性能更可控
因为代理类是目标类的直接子类,方法调用走的是普通继承链+MethodProxy.invokeSuper,避免了JDK代理中接口方法→反射invoke→目标方法的多层跳转。尤其在高频调用场景下,这种基于字节码的直调方式延迟更低、开销更稳。
Spring默认采用正是看中这点
Spring Boot 2起已统一默认使用CGLIB,不再按“有无接口”切换代理策略。这不是为了强行统一,而是实践发现:多数业务类本就不为代理而设计接口;强制接口化反而增加抽象负担。CGLIB让开发者专注写类,AOP能力自动跟上,织入时机、范围、逻辑完全由切面规则控制,不侵入业务代码结构。
它对final类或final方法无能为力,但这恰恰是设计取舍——用明确的约束换来了对普通Java类最直接、最轻量的增强支持。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











