JDK动态代理为什么基于接口而不基于类?

引言

在面试中很多时候会回答到JDK动态代理的相关问题,那么我们都知道JDK动态代理是基于接口的,如果被代理类没有实现某个接口,则无法使用JDK动态代理,而只能选择CGLIB代理。那么JDK动态代理为什么得基于接口,而不能兼容基于类呢?下面我们一起来讨论一下这个问题。

Java不支持多继承机制

我们知道Java不支持多继承(不能同时继承两个类),而是能通过实现接口的方式实现多继承的这种形式。

而这就是JDK动态代理基于接口,而不能基于类的原因。

JDK 动态代理是通过 Proxy.newProxyInstance() 在运行期生成一个 "实现目标接口的类",该代理类的父类始终是 java.lang.reflect.Proxy,不是你的目标类。代理类不能继承目标类,它不可能同时 extends Proxy 和 extends 你自己的类。

java 复制代码
代理类 extends Proxy implements 你的接口们

JDK 动态代理是怎么生成类的

ok,上面说了JDK动态代理不能基于类的根本原因,那么他是怎么根据我们自己的类生成代理类的呢?

如果你写:

java 复制代码
UserService proxy = (UserService) Proxy.newProxyInstance(...);

JDK 会动态生成一个代理类(可以 dump 出文件看到),类似:

java 复制代码
public final class $Proxy0 extends Proxy implements UserService {
    public void create() {
        // 所有方法最终转发到 InvocationHandler.invoke(...)
        h.invoke(this, method, args);
    }
}

所以你能看到很重要的三点:

第一,代理类固定继承 Proxy

第二,代理类不会继承你的实现类

第三,代理类通过实现接口,所有方法都是转发到 InvocationHandler

上面就是JDK动态代理怎么生成类的大概流程

那为什么CGLIB可以基于类

因为 CGLIB 跟 JDK 动态代理完全不一样,它不是用 Proxy API,它是:

  • 直接用 ASM 操作字节码
  • 生成目标类的子类
  • 通过重写方法进行拦截
java 复制代码
class UserServiceImpl$$EnhancerByCGLIB extends UserServiceImpl {
    @Override
    public void create() {
        // 调用 MethodInterceptor
    }
}

面试级总结❤️

JDK 动态代理不能基于类的根本原因:

JDK 动态代理基于接口实现,生成的代理类固定继承自 Proxy,而 Java 不支持同时继承目标类,因此无法对类本身做代理。

CGLIB 能代理类的原因:

CGLIB 直接生成目标类的子类,通过字节码增强实现方法拦截,不依赖接口,不依赖 Proxy 的父类结构。

相关推荐
Escalating_xu几秒前
【System V 信号量】从 P/V 原语到 Builder 封装:写出可控、可清理的进程互斥组件
java·linux·开发语言·jvm
今天AI了吗5 分钟前
什么是 AI Agent?它与直接调用大模型 API 有何区别
java·网络·人工智能·架构·java-ee
隐退山林7 分钟前
JavaEE进阶:SpringAOP
java·java-ee
大哥430910 分钟前
AI 接口高并发 ≠ 秒杀高并发:为什么我把并发闸门挂在 LLM 调用汇聚点
后端
Wang's Blog14 分钟前
Java框架快速入门: Spring Security+OAuth2之方法级安全注解
java·安全·spring
大哥430921 分钟前
Redis 主从下的库存一致性:我推翻了"付款前查库存"这个方案
后端
ikoala23 分钟前
DeepSeek 官方仓库惊现 DeepSeek Harness 桌面端!
前端·javascript·后端
JavacKaka31 分钟前
LiteFlow规则引擎实战博客-2026-09-09
java
学渣超36 分钟前
记一次复杂业务功能重构——从过程式长链路,到模板方法构建体系
java·架构·代码规范
用户4085274441439 分钟前
一个个人开发者,怎么啃下 12 种工控协议?
后端