你一定能看懂的JDK动态代理

扣子智能体平台深度解读:功能剖析与全流程工作流详解 这篇文章带着大家详细了解了扣子智能体平台的四个核心模块 ——“编排”“插件”“工作流” 和 “触发器”,把从设计流程到扩展功能、从执行逻辑到事件响应的整套能力都讲明白了。 阅读详情


卡通买书

前言:阅读这篇文章前,一定要知道什么是代理模式,具体可以参考这篇文章《设计模式(一):代理模式》。

在《设计模式(一):代理模式》一文中说了,程序员思思买书有两种选择:一种是选择去书厂(目标对象)买;另一种则是去书店(代理对象)买。第二种方式可以称为静态代理,因为这个代理对象是我们自己编写的。而JDK动态代理则是一种系统自动为我们生成代理对象的方式,下面先介绍一下这种方式如何实现。

一、JDK动态代理


首先还是有一家书厂,并且宣称自己有思思想要的书卖。

public interface Book {
    public void buyBook();
}
public class BookFactory implements Book{
    @Override
    public void buyBook() {
        System.out.println("思思买的书来自书厂");
    }
}

现在思思将使用JDK动态代理的方式去买到和书厂一模一样的书,那应该怎么做呢?

首先思思要找到一个 “神秘人” ,这个人专做各种倒买倒卖的生意。

public class MysteryMen implements InvocationHandler{
    private Object target; //思思需要告诉神秘人她想买书厂的书
    public MysteryMen(Object target){ 
        this.target = target;
    }
    //下面是神秘人做的事情,他能帮思思买到书,暂时不用管是怎么做到的。
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("神秘人开始买书");
        method.invoke(target, args);
        System.out.println("神秘人完成买书");
        return null;
    }
}

找到神秘人买书后,神秘人告诉思思还必须填写下面这个承诺表,才能将书给她。

public static Object newProxyInstance(ClassLoader loader,
                                      Class<?>[] interfaces,
                                      InvocationHandler h)

思思可是程序员啊,这自然难不倒她,下面是思思买书的具体步骤。

public class SiSi {
    public static void main(String[] args) {
        Book book = new BookFactory();
        MysteryMen  mysteryMen = new MysteryMen(book);
        Book dynamicBookStore = (Book)Proxy.newProxyInstance(BookFactory.class.getClassLoader(), 
                BookFactory.class.getInterfaces(), mysteryMen);
        dynamicBookStore.buyBook();
    }
}

执行 main 方法,结果如下:


买书

二、代码分析


结合上面的例子,下面对整个动态代理的过程做一个简单的梳理。

综合上一篇文章《设计模式(一):代理模式》可以看到,动态代理与静态代理有一个最大的不同点,就是静态代理需要自己编写代理类,即《设计模式(一):代理模式》中的 BookStore 类,再在 main 方法中执行 bookStore.buyBook()方法来达到目的。而使用动态代理时,这个代理对象是由系统在运行时为我们动态生成的。那系统到底是怎么为我们生成动态代理对象的呢?

首先看示例中,Proxy 类是JDK为我们提供的,它的 newProxyInstance 方法源码是这样写的:

*@param   loader the class loader to define the proxy class
*@param   interfaces the list of interfaces for the proxy class
*         to implement
*@param   h the invocation handler to dispatch method invocations to
*@return  a proxy instance with the specified invocation handler of a
*          proxy class that is defined by the specified class loader
*          and that implements the specified interfaces
public static Object newProxyInstance(ClassLoader loader,
                                      Class<?>[] interfaces,
                                      InvocationHandler h)
  • 第一个参数是一个类加载器,这个类加载器必须是加载目标对象字节码的类加载器。
  • 第二个参数是指定把动态生成的代理对象挂载到哪个接口下,此处是让动态代理对象与目标对象实现了同一个接口 Book。
  • 第三个参数,也是最为重要的一个参数,需要一个InvocationHandler接口的实现类。
  • 这个方法返回的是一个动态代理对象。

如果上面的参数不是很理解。具体到文中的例子,应该写成这样:Proxy.newProxyInstance(BookFactory.class.getClassLoader(),
BookFactory.class.getInterfaces(), mysteryMen)

InvocationHandler接口的源码如下:

public interface InvocationHandler {

    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}

结合上面的例子来看,我们在 invoke 方法里写了这样一段代码method.invoke(target, args),这段代码涉及到 Java 反射的内容,相当于通过反射调用了 BookFactory 中的 buyBook 方法。

那系统是怎么知道要去调用BookFactory方法的呢?

使用Debug调试可以看到:


动态代理01

  • method就是 buyBook 方法。
  • 而args是方法参数,此处为 null。
  • $Proxy0就是系统为我们动态生成的代理对象。通过在 main 方法里加上System.out.println(dynamicBookStore.toString)可验证。

method.invoke(target, args)中还有一处还没有说到,那就是第一个参数target。这个参数为系统指明了调用哪个实现类的 buyBook 方法。在示例中我们通过构造函数的传参的方式,在MysteryMen类中传入了一个 BookFactory 类的引用,也是为了反射调用目标方法做准备的。

至此我们重新梳理一下整个动态代理的过程。

三、动态代理过程解析


结合文章开始的例子,要写一个动态代理,首先得有个接口(Book)和该接口的实现类(BookFactory),这里的实现类其实就是被代理对象,或者称为目标对象 target ;然后写一个 InvocationHandler 实现类,这个实现类的 invoke 方法里包含着我们的处理逻辑,例如对目标对象方法的调用,或者添加上我们自己想要实现的处理逻辑;最后通过 Proxy 类的静态方法 newProxyInstance 来生成动态代理对象。

再次使用Debug调试,将断点打在dynamicBookstore.buyBook()处,再单步进入此方法可以看到,程序立刻跳入了 MysteryMen 的 invoke 方法:
debug

这张图说明了一点,那就是执行dynamicBookstore.buyBook()方法其实是执行了 InvocationHandler 接口实现类的 invoke 方法,invoke 方法里才是真正的处理逻辑地方。

在 invoke 方法里我们可以做任何我们想要的处理逻辑,例如在反射调用方法前后做一些操作,甚至不执行对目标方法的反射调用。

三、动态代理的优势


目前来说,我们使用动态代理完成的功能都能换用静态代理来完成。那么如此的话,动态代理到底有什么优势呢?

在静态代理中,一个目标对象对应这一个代理对象,如果目标对象过多,将会加重程序的代码量。而对于动态代理来说,如果我们想要对多个类进行代理,只需通过 newProxyInstance 方法让程序为我们动态生成代理对象即可,减少了代码工作量。并且在目标对象和动态代理对象之间还增加了一层 InvocationHandler 对目标方法进行拦截,一定程度上实现了解耦。

还有最重要的一点,就是静态代理在编译期间就需要指定对哪一个类进行代理,并写好该类的代理类。而动态代理则可以在运行期间确定需要对哪一个类进行代理,增加了系统的灵活性,其中运用了 Java 反射技术。

平台上新 | 文心智能体支持「工作流」 什么是工作流?工作流是用来干什么的?让我们一探究竟~ 阅读详情

相关推荐

jdk动态代理实现原理

JDK 动态代理是什么 在了解JDK动态代理前,有需要可以了解下代理模式 参考:https://blog.youkuaiyun.com/yhl_jxy/article/details/52679882 JDK 的动态代理是基于拦截器和反射来实现的 JDK代理是不需要第三方库支持的,只需要 JDK 环境就可以进行代理,使用条件: 必须实现 InvocationHandler 接口 使用 Proxy.newProxyInstance 产生代理对象 被代理的对象必须要实现接口 JDK 动态代理简单实现 使用 JDK 动态

桐花思雨 4081

【AI】推荐12个AI智能体应用开发平台

人工智能(AI)已经成为推动创新和增长的关键力量。无论是在医疗、金融、教育还是零售行业,AI的应用都在不断扩展,为各行各业带来革命性的变化。本文将介绍12个AI Agent和AI应用开发平台,平台的兴起,为广泛的用户群体提供了一个易于访问、成本效益高的解决方案,AI技术和应用不再是大公司的专属。AI应用开发平台通过提供预训练的模型、拖放界面和丰富的API,非技术用户也能快速构建和部署自己的AI应用。

赵英超的博客 3万+

jdk动态代理和cglib动态代理对比

JDK 动态代理:只代理接口(interface),无法代理类。它使用java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口来实现动态代理。 CGLIB 动态代理:可以代理类和接口。它通过生成目标类的子类来创建代理对象,因此可以代理没有实现接口的类。

zfj321的博客 1544

自建企业级AI智能体平台:工作流引擎与私有化部署实践

随着大模型技术深入业务场景,AI智能体正在从单点工具演变为企业核心生产力的基础设施。众所周知,通用Agent平台在快速验证创意时优势明显,但落到合规、可控、可审计的生产环境,往往受限于数据出域、流程绑定和成本核算等现实约束。本文从工作流引擎的分层设计出发,剖析DAG调度、并行控制、人工审批节点以及计划-执行模式等关键实现原理,并进一步探讨私有化部署、多租户隔离和Token成本治理等工程实践。通过多个真实踩坑案例,分享如何构建一套能与企业内部系统深度耦合、且具备全链路可观测性的AI智能体底座,为企业智能化转型

weixin_29041767的博客 249

从零开始,手把手教你用RTL代码设计一个简单的8位CPU(附状态图与ALU设计)

本文详细介绍了如何从零开始设计一个简单的8位CPU,包括状态机设计、ALU实现与RTL编码实战。通过具体的指令集分析、状态图设计和Verilog代码示例,帮助读者深入理解CPU工作原理,并掌握RTL代码编写技巧。特别适合计算机系统学习者和硬件设计爱好者。

weixin_30847063的博客 320

手把手教你用Matlab搞定GRACE RL06数据读取:冯伟老师工具箱无GUI版实战

本文详细介绍了如何使用Matlab处理GRACE RL06数据,重点解析了冯伟教授工具箱的无GUI版实战操作。通过环境配置、核心函数改造和批处理技巧,帮助科研工作者高效完成重力场数据的读取与分析,特别适合服务器集群环境下的批量处理需求。

weixin_29313817的博客 200

无需写代码,开源界最强智能体平台!

​从零到一:搭建可商用的开源AI智能体在线实训系统(基于Dify/扣子/n8n/BuildingAI) ​

Zmq83906955的博客 680

Linux下科大讯飞离线语音识别SDK从下载到实战(附常见问题解决)

本文详细介绍了在Linux系统下,如何从科大讯飞开放平台获取离线语音识别SDK,完成环境准备、编译部署到实战开发的完整流程。文章重点解析了SDK目录结构、语法词典定制、示例代码修改,并针对开发中常见的“词典加载失败”、音频格式、交叉编译及性能优化等问题提供了深度解决方案,助力嵌入式与IoT开发者快速实现稳定可靠的离线命令识别功能。

honey的博客 1241

JDK动态代理、Cglib动态代理及Spring AOP

Java中的JDK动态代理是一种通过反射机制生成代理对象的技术,使得我们能够在运行时动态地创建某个接口的代理类,而无需手动编写实现类。JDK动态代理通常用于横切关注点(如日志、事务管理、安全性等)在方法调用前后进行处理,而不需要修改目标类的源代码。

意疏的博客 6385

AUTOSAR R20-11标准下载!

这是公众号的第2篇推文,粉丝数49 Document Search Classic Platform Adaptive Platform Foundation 文档截图 以为会在明天的发布会之后才上线,没想到官网现在就悄悄放出来了。 中国由于网络问题,下载速度比较慢或者会中断。 “阅读原文”提供多种下载方式,可以在线浏览,可以集中下载也可单个文档下载。 如有增减我也会及时在公众号里通知大家,不过我觉得不会变动了。 整理不宜,好东西要分...

Adaptive_AUTOSAR的博客 1891

基于非接触式微波雷达设计的跌倒检测预警系统【短信报警】

本项目选择基于非接触式微波雷达的跌倒检测预警装置作为技术核心,采用云帆瑞达的R60AFD1跌倒检测模组。这一模组能够根据人体的运动变化,如速度、距离和姿态等特征,判断是否发生跌倒,并可以持续监控老年人是否处于危险状态。此外,本项目还结合4G通信技术,通过Air724UG模块实现短信报警功能,一旦检测到跌倒事故,系统将自动通过4G网络向紧急联系人发送短信报警,及时通知亲属或医护人员进行救援。

1755

Java中的JDK动态代理

Java中JDK动态代理,AOP是对动态代理的进一步规范化,CGLB动态代理

weixin_44362089的博客 5562

rk3588平台USB 3.0 -OAK深度相机适配方法

摘要:本文记录了OAK摄像头设备的配置与测试流程。主要内容包括:1)添加USB设备udev规则;2)拉取相关依赖库;3)安装Python3和pip;4)安装项目依赖;5)安装FFmpeg工具;6)测试摄像头功能并转换视频格式;7)将测试视频拷贝到U盘查看。操作步骤涵盖了从设备驱动配置到功能测试的完整流程,提供了详细的命令行操作指引。通过该文档可快速完成OAK摄像头的环境搭建和基础功能验证。

yy_hear的博客 325

JDK动态代理和CGLIB动态代理有什么区别?

JDK动态代理和CGLIB动态代理有什么区别?

水w的博客 8019

Orange3实战教程:文本挖掘---主题建模

主题建模通过LDA、LSI或HDP算法分析文档集合,自动发现隐含主题结构。组件输入为文档语料库,输出包括带主题权重的语料库、主题词分布及完整主题数据。不同算法特性各异:LSI允许正负权重但解释性较弱,LDA更易解释,HDP参数复杂需谨慎设置。结果可结合词云、热力图等可视化工具分析主题特征及分布。示例显示如何通过预处理文本、选择算法(如提取5个LDA主题),并利用MDS和箱线图探索主题间关系及关键词分布。

err2008的专栏 365

7、基于机器学习的生产效率估计方法解析

本文探讨了基于机器学习的生产效率估计方法,重点介绍了效率分析树(EAT)和凸效率分析树(CEAT)算法的原理及其与传统自由处置壳(FDH)和数据包络分析(DEA)方法的对比。通过剪枝优化、生产可能性集构建及方向距离函数(DDF)估计,EAT和CEAT在避免过拟合、提升估计稳定性与处理凸性假设方面展现出优势。结合PISA教育数据的实证研究,采用箱线图、核密度图和非参数检验方法验证了不同模型效率得分分布的显著差异。研究表明,EAT与CEAT为生产效率评估提供了更准确、灵活的工具,适用于教育、企业生产和医疗等多个

milk5的博客 93

Java——JDK动态代理

动态代理是指代理类对象在程序运行时由JVM根据反射机制动态生成的。动态代理不需要定义代理类的,java源文件。动态代理其实就是jdk运行期间,动态创建class字节码并加载到JVM。动态代理的实现方式常用的有两种:使用JDK代理,与通过CGLlB动态代理。

m0_73671382的博客 7677

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

JDK动态代理

代理模式【proxy】是对象的结构模式,代理模式给某一个对象提供一个代理对象,并由代理对象控制对象的引用。代理就是⼀个⼈或者⼀个机构代表另⼀个⼈或者另⼀个机构采取⾏动。在⼀些情况 下,⼀个客户不想或者不能够直接引⽤⼀个对象,⽽代理对象可以在客户端和⽬标对象之间 起到中介作⽤。代理模式的主要⽬标是:保护(隔离)和增强⽬标对象。

qq_59308271的博客 999

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

深入理解JDK动态代理

深入理解JDK动态代理

abcafdsgr123456789的博客 1835

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

JDK动态代理理解

代理模式说是一种“结构性设计模式” ,其核心思想是通过一个代理对象(proxy)间接访问目标对象(target),从而在不修改对象的前提下,实现对目标对象的控制或者功能增强。抽象角色: 定义目标对象和代理对象的共同接口(如java的接口)真实角色:实现抽象接口的具体业务逻辑类代理对象:持有真实角色的引用,并在其基础上拓展功能(如日志,事务等)举个例子:假设需要租房的时候,租客并不志杰联系房东,而是联系中介。

m0_60963435的博客 1834

SpringAOP JDK动态代理

目前我本人正在学习SpringFramework的知识,这也是这个专栏的主题。我前面的几篇博文中,简单的认识了一下SpringFramework,记录了SpringFramework的环境搭建,记录了SpringIOC如何加载配置文件,记录了SpringIOC三种Bean对象的实例化方法。还记录了SpringIOC手动装配(注入)的方法之一:set方法注入。还有另外三个不太常用的SpringIOC手动注入的方法。其实目前大部分都使用的是自动注入的方法,手动注入使用的不多。就算是使用手动注入的方法,使用的主流

weixin_46281472的博客 3303

深入解析JDK动态代理

JDK动态代理是一种运行时创建代理类的技术,可以在不修改原始类代码的情况下为其添加新的功能。与静态代理不同,JDK动态代理不需要在编译时创建代理类,而是通过反射在运行时生成代理类。首先,我们定义一个接口,这个接口将由代理类实现。JDK动态代理是Java开发中一个非常有用的工具,可以在运行时为对象添加额外的功能,而无需修改原始代码。它主要通过Proxy类和InvocationHandler接口实现,具有很高的灵活性和扩展性。

qq_44266019的博客 1905

JDK动态代理与CGLIB动态代理

设计模式之代理模式 下面假设一个常见的场景,假如你有一个法国的朋友叫Aice,有一天你想要购买一瓶法国香奈儿的香水,这种香水只在法国销售。你找到你的朋友Alice,请求她帮忙购买一瓶香奈儿的香水,你的朋友Alice于是乎就找到香奈儿的销售店购买了一瓶法国香奈儿的香水,并将香水交给了你。 在上面这个例子当中,你想要购买法国香水,但是无法直接向香奈儿供应商购买,只能通过中间人(Alice)购买,这就是我们生活中比较常见的代理模式。我们假设有一天,你突然想要一瓶法国红酒,但是由于Alice本身并不具备购买红

weixin_43529092的博客 3323

简单实现jdk的动态代理

简单实现jdk的动态代理 jdk动态代理的使用 package com.util; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class Test { //产生代理对象 public static ...

小王同学的博客 2070

JDK动态代理 VS Cglib动态代理

提到了动态代理就不得不提到静态代理和动态代理的区别了。动态代理和静态代理是两种常见的代理模式,在软件开发中经常被用来实现对象间的间接访问。它们之间的主要区别在于代理对象的生成时机和方式。静态代理和动态代理都是为了实现对象间的间接访问,通过代理对象来控制对目标对象的访问。静态代理在编译时就已经确定了代理对象,而动态代理是在运行时生成代理对象。静态代理需要为每个被代理类创建一个代理类,而动态代理可以动态地为多个类创建代理对象。动态代理相对于静态代理更加灵活,但实现机制相对复杂。

m0_68570169的博客 1403
上一篇: 设计模式(一):代理模式
下一篇: 设计模式之单例模式
KKSJS
博客等级 码龄9年 16粉丝 19原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值