前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Java的动态代理

Java的动态代理

作者头像
闻说社
发布于 2025-02-27 07:57:21
发布于 2025-02-27 07:57:21
11700
代码可运行
举报
运行总次数:0
代码可运行

Java的动态代理

以下是Java动态代理的逐步解释:

Java动态代理详解
1. 动态代理的核心组件
  • java.lang.reflect.Proxy:生成代理对象的工具类。
  • java.lang.reflect.InvocationHandler:代理对象的方法调用处理器接口。
2. 实现步骤

步骤1:自定义接口

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
java 代码解读复制代码public interface UserService {
    void addUser(String username);
    void deleteUser(String username);
}

步骤2:实现自定接口

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
java 代码解读复制代码public class UserServiceImpl implements UserService {
    @Override
    public void addUser(String username) {
        System.out.println("添加用户: " + username);
    }

    @Override
    public void deleteUser(String username) {
        System.out.println("删除用户: " + username);
    }
}

步骤3:实现InvocationHandler

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
java 代码解读复制代码import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class LoggingHandler implements InvocationHandler {
    private final Object target; // 被代理的对象

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 方法执行前逻辑
        System.out.println("调用方法前: " + method.getName());
        
        // 执行目标方法
        Object result = method.invoke(target, args);
        
        // 方法执行后逻辑
        System.out.println("调用方法后: " + method.getName());
        return result;
    }
}

步骤4:生成代理对象

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
java 代码解读复制代码import java.lang.reflect.Proxy;

public class DynamicProxyDemo {
    public static void main(String[] args) {
        // 创建目标对象
        UserService realService = new UserServiceImpl();
        
        // 创建InvocationHandler实例
        InvocationHandler handler = new LoggingHandler(realService);
        
        // 生成代理对象
        UserService proxyService = (UserService) Proxy.newProxyInstance(
            UserService.class.getClassLoader(), // 类加载器
            new Class[]{UserService.class},     // 代理的接口数组
            handler                             // InvocationHandler实例
        );
        
        // 通过代理对象调用方法
        proxyService.addUser("Alice");
        proxyService.deleteUser("Bob");
    }
}
3. 输出结果
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
makefile 代码解读复制代码调用方法前: addUser
添加用户: Alice
调用方法后: addUser

调用方法前: deleteUser
删除用户: Bob
调用方法后: deleteUser
4. 动态代理的底层原理
  • 代理类生成Proxy.newProxyInstance() 在运行时动态生成代理类字节码。
  • 代理类结构:生成的代理类继承 Proxy 并实现指定接口。
  • 方法调用流程
    1. 客户端调用代理对象方法(如 addUser())。
    2. 代理类将调用转发到 InvocationHandler.invoke()
    3. invoke() 方法执行前置逻辑 → 调用目标方法 → 执行后置逻辑。
5. 动态代理的限制与解决方案

限制

说明

解决方案

只能代理接口

无法直接代理没有接口的类

使用CGLIB库(如Spring AOP默认行为)

性能开销

反射调用比直接调用慢约5-20倍

对性能敏感场景使用AspectJ编译时织入

无法代理final方法

final方法无法被重写

避免代理final方法或使用CGLIB

6. 动态代理的典型应用场景
  • AOP实现:日志、事务、权限校验等横切关注点。
  • 远程方法调用(RPC):如Dubbo、gRPC的客户端代理。
  • 延迟加载:例如Hibernate的延迟初始化代理。
  • Mock测试:动态生成测试替身(Test Double)。
7. 动态代理与CGLIB对比

特性

JDK动态代理

CGLIB

代理方式

基于接口

基于类继承

性能

较慢(反射调用)

较快(方法调用无反射)

依赖

无需第三方库

需要引入CGLIB库

方法限制

无法代理无接口的类

无法代理final方法或类

8. 高级技巧

查看生成的代理类字节码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
java 代码解读复制代码// 在启动JVM时添加以下参数
System.setProperty("jdk.proxy.ProxyGenerator.saveGeneratedFiles", "true");

处理Object方法(如toString)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
java 代码解读复制代码@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    if (method.getDeclaringClass() == Object.class) {
        // 直接调用Object方法,不进行代理增强
        return method.invoke(target, args);
    }
    // 其他方法的代理逻辑
    // ...
}

动态代理实现RPC框架伪代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
java 代码解读复制代码public class RpcProxy implements InvocationHandler {
    private final String host;
    private final int port;

    public RpcProxy(String host, int port) {
        this.host = host;
        this.port = port;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) {
        // 1. 序列化请求参数
        byte[] requestData = serialize(method, args);
        
        // 2. 发送网络请求
        byte[] responseData = sendRequest(host, port, requestData);
        
        // 3. 反序列化响应结果
        return deserialize(responseData, method.getReturnType());
    }
}
9. 总结
  • 核心机制:通过反射动态生成代理类,拦截方法调用。
  • 适用场景:需要无侵入式增强方法功能的场合。
  • 性能权衡:灵活性与性能之间的取舍,需根据场景选择方案。
  • 扩展应用:结合其他技术(如注解、反射工厂)可实现更复杂的功能增强。

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
动态代理的两种方式以及优缺点
动态代理应用非常的广泛,在各种开源的框架中都能看到他们的身影,比如spring中的aop使用动态代理增强,mybatis中使用动态代理生成mapper,动态代理主要有JDK和CGLIB两种方式,今天来学习下这两种方式的实现,以及它们的优缺点
全栈程序员站长
2022/07/04
5790
动态代理的两种方式以及优缺点
Java 动态代理初探
对于使用过 Spring 的朋友, 应该都使用过 AOP, 那么今天我们来对 AOP 的原理: 动态代理 来一探究竟.
一份执着✘
2019/12/30
3580
jdk静态代理,jdk动态代理,cglib动态代理
代理是什么呢?举个例子,一个公司是卖摄像头的,但公司不直接跟用户打交道,而是通过代理商跟用户打交道。如果:公司接口中有一个卖产品的方法,那么公司需要实现这个方法,而代理商也必须实现这个方法。如果公司卖多少钱,代理商也卖多少钱,那么代理商就赚不了钱。所以代理商在调用公司的卖方法后,加上自己的利润然后再把产品卖给客户。而客户部直接跟公司打交道,或者客户根本不知道公司的存在,然而客户最终却买到了产品。
互扯程序
2019/07/01
5050
jdk静态代理,jdk动态代理,cglib动态代理
JDK动态代理和CGLIB动态代理
Java动态代理是一种在运行时创建代理对象的技术,它允许开发者在不修改目标类代码的情况下,通过代理类对目标类的实例方法进行增强或拦截。动态代理的核心价值在于能够在程序运行阶段动态地生成一个实现了预定义接口的新类,这个新类就是所谓的“代理类”。
程序猿川子
2025/02/27
1650
JDK动态代理和CGLIB动态代理
探索Java动态代理的奥秘:JDK vs CGLIB
动态代理是一种在 运行时动态生成代理类 的技术,无需手动编写代理类代码。它通过拦截目标方法的调用,实现对核心逻辑的 无侵入式增强(如日志、事务、权限控制等)。
用户7954602
2025/02/04
1500
探索Java动态代理的奥秘:JDK vs CGLIB
Java中的动态代理以及在框架中的应用
我们先假设现在有怎么一个需求,要求你在不改动原有代码的情况下在所有类的方法前后打印日志。我们很容易想到静态代理,具体做法如下:
烂猪皮
2021/06/09
1.5K0
Java中的动态代理以及在框架中的应用
Java 动态代理详解
动态代理在Java中有着广泛的应用,比如Spring AOP、Hibernate数据查询、测试框架的后端mock、RPC远程调用、Java注解对象获取、日志、用户鉴权、全局性异常处理、性能监控,甚至事务处理等。
小旋锋
2019/01/21
1.1K0
Java设计模式:代理模式的静态和动态之分(八)
码到三十五 : 个人主页 心中有诗画,指尖舞代码,目光览世界,步履越千山,人间尽值得 !
公众号:码到三十五
2024/04/09
1410
Java设计模式:代理模式的静态和动态之分(八)
Spring AOP动态代理
本文将介绍如何使用 AOP 实现动态代理,并以 GitHub 风格的方式展示其实现过程。
人不走空
2024/02/25
1740
Spring AOP动态代理
第06天 静态代理和动态代理
代理模式是一种比较好理解的设计模式。简单来说就是 我们使用代理对象来代替对真实对象 (real object) 的访问,这样就可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。
程序员Leo
2023/08/16
1940
第06天 静态代理和动态代理
Java 静态代理、Java动态代理、CGLIB动态代理
Java 的代理就是客户类不再直接和委托类打交道, 而是通过一个中间层来访问, 这个中间层就是代理。为啥要这样呢, 是因为使用代理有 2 个优势:
java思维导图
2019/05/21
7.1K0
【面试题精讲】JDK动态代理
JDK 动态代理是 Java 中一种实现代理模式的机制。它允许在运行时创建代理类和对象,用于替代原始对象进行方法调用,并可以在方法调用前后添加额外的逻辑。
程序员朱永胜
2023/10/10
5200
016 Java中的动态代理
代理 代理模式是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个真实对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。 代理可以实现过滤请求、插入横切逻辑等功能,应用场景丰富多彩。 代理的方式分为静态代理和动态代理两种。 静态代理 程序运行前代理类的字节码文件依然存在,需要程序员编写源文件。 缺点:要针对于每一个类撰写代理类;对于单个被代理的类,如果需要被代理的方法很多,又加大了工作量。 优点:直观,可读性较强。 动态代理 程序运行时动态生成
nnngu
2018/03/15
7460
016 Java中的动态代理
深度解析 Spring 源码:揭秘JDK动态代理的奥秘
JDK动态代理是Java语言提供的一种实现动态代理的方式,其基本原理是利用反射机制在运行时动态生成代理类和代理对象。
忆愿
2025/01/06
2270
深度解析 Spring 源码:揭秘JDK动态代理的奥秘
探究动态代理与CGLIB的奥秘:Java代理模式的两种实现方式
在Java开发中,代理模式是一种常见的设计模式,它允许我们创建一个代理对象,用来控制对其他对象的访问。代理模式在AOP(面向切面编程)中广泛应用,用于实现日志记录、性能监测、事务管理等功能。在代理模式中,有两种主要的实现方式:动态代理和CGLIB代理。本文将深入研究这两种代理方式的区别,分析它们的优缺点,并提供代码示例,帮助你更好地理解和应用这些概念。
疯狂的KK
2023/09/27
2.9K0
探究动态代理与CGLIB的奥秘:Java代理模式的两种实现方式
设计模式 - 动态代理
代理模式:给某一个对象提供一个代理,并由代理对象来控制对真实对象的访问。代理模式是一种结构型设计模式。(逐字理解)
用户7630333
2023/12/07
1720
设计模式 - 动态代理
java动态代理和静态代理的实现
代理模式:为其他对象提供一种代理以控制目标对象的访问,在某些情况下, 一个对象不适合或者不能直接引用另外一个对象,代理对象可以在这个客户类和目标对象中起到一个桥梁作用。
IT云清
2019/01/22
4370
静态代理与动态代理
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/details/52025353
DannyHoo
2018/09/13
3520
静态代理与动态代理
AOP中的JDK动态代理与CGLIB动态代理:深度解析与实战
这里推荐一篇实用的文章:《Java 读取寄存器数据的实现与应用》,作者:【喵手】。
小马哥学JAVA
2024/11/21
2210
(86) 动态代理 / 计算机程序的思维逻辑
前面两节,我们介绍了反射和注解,利用它们,可以编写通用灵活的程序,本节,我们来探讨Java中另外一个动态特性 - 动态代理。 动态代理是一种强大的功能,它可以在运行时动态创建一个类,实现一个或多个接口,可以在不修改原有类的基础上动态为通过该类获取的对象添加方法、修改行为,这么描述比较抽象,下文会具体介绍,这些特性使得它广泛应用于各种系统程序、框架和库中,比如Spring, Hibernate, MyBatis, Guice等。 动态代理是实现面向切面的编程(AOP - Aspect Oriented
swiftma
2018/02/01
5250
相关推荐
动态代理的两种方式以及优缺点
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验