跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava

Java 动态代理核心原理与实战对比

Java 动态代理通过运行时反射生成代理类,无需手动编写。主要包含 JDK 动态代理(基于接口)和 CGLIB 动态代理(基于子类)。JDK 原生轻量但需接口,CGLIB 功能更强但依赖第三方库。Spring AOP 默认优先使用 JDK,无接口时切换 CGLIB。掌握两者差异有助于优化框架设计与性能调优。

kaikai发布于 2026/3/26更新于 2026/7/2338 浏览
Java 动态代理核心原理与实战对比

Java 动态代理核心原理与实战对比

在 Java 开发中,代理模式是设计模式的经典应用,而动态代理作为其进阶形式,在框架开发(如 Spring AOP)、日志记录、权限控制等场景中发挥着关键作用。它允许我们在程序运行时动态生成代理类,而非在编译期预先定义。

动态代理概念图

一、动态代理的核心概念

动态代理的核心价值在于:无需为每个目标类手动编写代理类,即可统一为多个目标类添加横切逻辑(如日志、事务、异常处理),从而降低代码耦合度。

动态代理主要包含三个核心角色:

  1. 目标类(Target):被代理的原始类,包含核心业务逻辑;
  2. 代理类(Proxy):运行时动态生成的类,持有目标类引用,负责调用目标方法并增强逻辑;
  3. 增强逻辑(Advice):需统一添加的横切逻辑,如日志打印、参数校验等。

动态代理结构

二、两种主流动态代理实现

Java 中动态代理主要有两种实现方式:JDK 动态代理(原生 API)和 CGLIB 动态代理(第三方库),二者在原理和使用上存在显著差异。

1. JDK 动态代理(基于接口)

原理

JDK 动态代理依赖 java.lang.reflect 包下的 Proxy 和 InvocationHandler 接口。要求目标类必须实现至少一个接口。运行时,JVM 会动态生成一个实现目标接口的代理类,代理类的方法调用会转发到 InvocationHandler 的 invoke 方法中,在该方法中可嵌入增强逻辑并调用目标方法。

JDK 动态代理流程

示例代码
// 1. 定义接口
public interface UserService {
    void addUser(String name);
}

// 2. 实现目标类
public class UserServiceImpl implements UserService {
    @Override
    public void addUser(String name) {
        System.out.println("添加用户:" + name);
    }
}

// 3. 实现 InvocationHandler(增强逻辑)
public class LogInvocationHandler implements InvocationHandler {
    private Object target;

    public LogInvocationHandler(Object target) {
        this.target = target;
    }

    // 代理类的所有方法调用都会触发 invoke
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 增强逻辑:前置日志
        System.out.println("方法 " + method.getName() + " 开始执行,参数:" + Arrays.toString(args));
        
        // 调用目标方法
        Object result = method.invoke(target, args);
        
        // 增强逻辑:后置日志
        System.out.println("方法 " + method.getName() + " 执行结束");
        return result;
    }
}

// 4. 生成代理类并测试
public class JdkProxyTest {
    public static void main(String[] args) {
        // 目标对象
        UserService target = new UserServiceImpl();
        
        // 生成代理对象(需传入类加载器、目标接口、InvocationHandler)
        UserService proxy = (UserService) Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            new LogInvocationHandler(target)
        );
        
        // 调用代理方法
        proxy.addUser("张三");
    }
}
优缺点
  • 优点:基于 JDK 原生 API,无需依赖第三方库,轻量化;
  • 缺点:目标类必须实现接口,无法代理无接口的类。

2. CGLIB 动态代理(基于子类)

原理

CGLIB(Code Generation Library)是一个第三方字节码生成库,通过生成目标类的子类作为代理类,无需目标类实现接口。其核心是 MethodInterceptor 接口,代理类的方法调用会被拦截到 intercept 方法中,在此处嵌入增强逻辑并调用目标方法。

示例代码(需引入 CGLIB 依赖)
<!-- Maven 依赖 -->
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>
// 1. 目标类(无需实现接口)
public class OrderService {
    public void createOrder(String orderId) {
        System.out.println("创建订单:" + orderId);
    }
}

// 2. 实现 MethodInterceptor(增强逻辑)
public class LogMethodInterceptor implements MethodInterceptor {
    // 拦截代理类方法调用
    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        // 增强逻辑:前置日志
        System.out.println("方法 " + method.getName() + " 开始执行,参数:" + Arrays.toString(args));
        
        // 调用目标方法(推荐用 methodProxy.invokeSuper,避免递归调用)
        Object result = methodProxy.invokeSuper(o, args);
        
        // 增强逻辑:后置日志
        System.out.println("方法 " + method.getName() + " 执行结束");
        return result;
    }
}

// 3. 生成代理类并测试
public class CglibProxyTest {
    public static void main(String[] args) {
        // CGLIB 核心类:Enhancer
        Enhancer enhancer = new Enhancer();
        
        // 设置父类(目标类)
        enhancer.setSuperclass(OrderService.class);
        
        // 设置方法拦截器
        enhancer.setCallback(new LogMethodInterceptor());
        
        // 生成代理对象(子类实例)
        OrderService proxy = (OrderService) enhancer.create();
        
        // 调用代理方法
        proxy.createOrder("ORDER_001");
    }
}
优缺点
  • 优点:无需目标类实现接口,可代理任意类(除 final 类和 final 方法);
  • 缺点:依赖第三方库,生成代理类时需操作字节码,性能略低于 JDK 动态代理(JDK 8 后差距已缩小)。

三、JDK 与 CGLIB 动态代理对比

对比维度JDK 动态代理CGLIB 动态代理
依赖JDK 原生 API(无第三方依赖)需引入 CGLIB 库
代理原理实现目标接口生成目标类子类
目标类要求必须实现接口无接口要求(不能是 final 类)
方法限制仅代理接口中的方法不能代理 final 方法
性能(JDK 8+)生成快,调用效率高生成慢,调用效率略低

四、实际应用场景

  1. Spring AOP:默认优先使用 JDK 动态代理(目标类有接口时),无接口时使用 CGLIB;
  2. 日志记录:统一记录方法的入参、出参、执行时间;
  3. 权限控制:方法调用前校验用户权限,无权限则抛出异常;
  4. 事务管理:方法执行前开启事务,执行后提交/回滚事务。

五、总结

动态代理是 Java 中'解耦横切逻辑'的核心技术。JDK 动态代理和 CGLIB 各有适用场景:若目标类已实现接口,优先选择 JDK 动态代理(轻量化、无依赖);若目标类无接口或需代理类的所有方法,选择 CGLIB。在实际开发中,理解两者的底层机制有助于更好地进行框架选型和性能调优。

目录

  1. Java 动态代理核心原理与实战对比
  2. 一、动态代理的核心概念
  3. 二、两种主流动态代理实现
  4. 1. JDK 动态代理(基于接口)
  5. 原理
  6. 示例代码
  7. 优缺点
  8. 2. CGLIB 动态代理(基于子类)
  9. 原理
  10. 示例代码(需引入 CGLIB 依赖)
  11. 优缺点
  12. 三、JDK 与 CGLIB 动态代理对比
  13. 四、实际应用场景
  14. 五、总结
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • RTX 4090 本地部署腾讯混元与阿里通义万相视频模型
  • Rust 十年路:所有权、零成本抽象与跨领域渗透
  • 低代码平台的两种价值观:短期成果与长期成本
  • MAVROS 安装配置与 ROS C++ 仿真实战指南
  • 数据结构初阶:二叉树的链式存储结构
  • Apache IoTDB 全场景部署:跨「端 - 边 - 云」的时序数据库实践
  • C++ 继承机制详解:从基础到多态
  • Neo4j 图数据库安装与操作指南
  • OpenClaw 接入自定义模型并通过 WebUI 实现智能操作
  • AI 大模型产品经理学习路线:从入门到精通
  • Coze 打造专属 AI 应用:从智能体到 Web 部署
  • 基于 Rokid AR 眼镜的会议纪要助手开发实录
  • C 语言代码优化与性能调优:编译器、内存与算法实战
  • 大模型时代:重构技术开发的生产与组织方式
  • AI Agent 开发入门:零基础也能学吗
  • S1: 仅 1k 样本,测试时扩展超越 OpenAI o1-preview 性能
  • GPT、LLaMA 与 MOE:自回归模型与混合专家架构演进
  • 构建与 GitHub 深度集成的自动化工作流指南
  • 通义万相 2.1 API 调用实战:Python 实现文生图与文本生成
  • GitHub 启用双因素身份验证 2FA 配置教程

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online