0

0

Java的动态代理怎么实现_JDK原生Proxy与InvocationHandler

P粉602998670

P粉602998670

发布时间:2026-03-16 09:48:39

|

736人浏览过

|

来源于php中文网

原创

Proxy.newProxyInstance 抛 IllegalArgumentException 因接口数组为 null、空或含非接口类;Object 方法会被代理并转发至 invoke;代理对象只能转接口不能转实现类;method.invoke 调用慢因反射开销大。

java的动态代理怎么实现_jdk原生proxy与invocationhandler

Proxy.newProxyInstance 为什么总抛 IllegalArgumentException

常见错误是传入的接口数组为 null、空数组,或里面混了非接口类(比如传了个 ArrayList.class)。JDK 要求必须全是 interface 类型,且不能重复。

实操建议:

立即学习Java免费学习笔记(深入)”;

  • 检查 interfaces 参数是否用 clazz.getInterfaces() 直接拿——它可能返回空数组(比如类没实现任何接口)
  • 手动构造时别写 new Class[]{MyClass.class},得是 new Class[]{MyInterface.class}
  • 如果目标类实现了多个接口,但只想代理其中一部分,必须显式列出,不能靠“继承关系”自动推导

InvocationHandler.invoke 的 method 参数为啥有时是 Object 的方法(toString/hashCode

这是正常现象。JDK 代理对象在初始化、打印、比较时会调用 Object 的公共方法,它们也会被转发到 invoke。不处理这些方法,代理对象可能表现异常(比如 System.out.println(proxy) 打印出 null 或报错)。

实操建议:

立即学习Java免费学习笔记(深入)”;

  • method.getDeclaringClass() == Object.class 的情况,通常直接调用 proxy.getClass().getName()System.identityHashCode(proxy) 做简单返回
  • 不要无条件反射调用 method.invoke(target, args),target 可能是 null 或根本没实现 toString
  • 如果用了 CGLIB 风格的“拦截所有方法”,这里就是第一个漏斗——JDK Proxy 天然只拦截接口方法,但 Object 方法是特例

为什么代理对象不能强转成具体实现类,只能转接口

因为 Proxy.newProxyInstance 生成的是一个新类,它只实现你传入的 interfaces,和原始实现类没有继承关系。JVM 类型系统不允许向下转型。

arXiv Xplorer
arXiv Xplorer

ArXiv 语义搜索引擎,帮您快速轻松的查找,保存和下载arXiv文章。

下载

实操建议:

立即学习Java免费学习笔记(深入)”;

  • 声明变量时就用接口类型:MyService service = (MyService) Proxy.newProxyInstance(...),别试图 (MyServiceImpl)
  • 如果业务代码里硬依赖实现类(比如反射取私有字段),说明设计已偏离接口抽象原则,Proxy 不是补丁工具
  • 需要类似功能?考虑 CGLIB 或 ByteBuddy,但要注意它们生成的是子类,无法代理 final 类或方法

InvocationHandler 里调用 method.invoke(target, args) 慢在哪

慢在反射本身:每次调用都要做访问检查、参数封装、类型匹配,尤其当 target 是普通对象(非 MethodHandle)时,JVM 很难内联优化。

实操建议:

立即学习Java免费学习笔记(深入)”;

  • method.setAccessible(true) 避免 SecurityManager 检查(开发/测试环境有效,生产需评估风险)
  • 高频场景下,缓存 MethodHandle:用 MethodHandles.lookup().unreflect(method) 替代反复反射调用
  • 注意 target 是否可能为 null——比如你代理的是无状态接口,target 根本不存在,这时 invoke 逻辑应完全自包含
代理的核心约束很实在:它只活在接口契约里,不认实现,不碰字节码,也不替你做决策。最容易被忽略的,是把 InvocationHandler 当成万能钩子,却忘了它的每次触发都意味着一次明确的接口方法调用——不是事件,不是回调,更不是 AOP 的切入点。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

254

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

1132

2024.03.01

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1998

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

681

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2418

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

49

2026.01.19

class在c语言中的意思
class在c语言中的意思

在C语言中,"class" 是一个关键字,用于定义一个类。想了解更多class的相关内容,可以阅读本专题下面的文章。

931

2024.01.03

python中class的含义
python中class的含义

本专题整合了python中class的相关内容,阅读专题下面的文章了解更多详细内容。

32

2025.12.06

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

90

2026.03.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 4.4万人学习

C# 教程
C# 教程

共94课时 | 11.4万人学习

Java 教程
Java 教程

共578课时 | 82.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号