java之动态代理

发布时间:2026/7/13 5:45:47

java之动态代理
目录[TOC](目录)前言1. 比喻理解2. 代码理解1. 签名2. 参数1ClassLoader loader (类加载器)3. 参数2Class?[] interfaces (接口数组)4. 参数3InvocationHandler h (调用处理器)3. 测试与运行4. 代理字节码原理总结前言通过一个通俗易懂的比喻快速理解 Java 动态代理的核心设计思想。通过手写 JDK 动态代理的完整代码详细剖析其核心参数与运行机制并深入 JVM 内存中的代理类字节码揭示动态代理的底层实现原理。1. 比喻理解例子大明星小美十分擅长唱歌和跳舞。打算举办演唱会举办演唱会的过程非常繁琐。小美只想把核心精力放在唱歌和跳舞上。代理小帅专门负责处理小美唱歌和跳舞之外的所有繁杂事务。赞助商希望小美来唱歌时不能直接和小美对话必须先和经纪人小帅交涉。调用过程小帅和赞助商谈妥后前置准备把小美带到舞台上小美只管唱歌核心业务。唱完歌后小帅还要负责结算收尾工作后置收尾。在这个过程中小帅就是小美的代理人也就是我们代码中常说的代理对象。2. 代码理解我们首先写一个接口叫做Star明星声明两个方法sing和dance。publicinterfaceStar{Stringsing(StringsongName);voiddance();}小美是大明星实现Star接口擅长sing与dancepublicclassBigStarimplementsStar{OverridepublicStringsing(StringsongName){System.out.println(小美正在唱songName);return谢谢大家;}Overridepublicvoiddance(){System.out.println(小美正在跳舞);}}接下来我们编写用于创建代理对象的工具类ProxyUtil。importjava.lang.reflect.InvocationHandler;importjava.lang.reflect.Method;importjava.lang.reflect.Proxy;publicclassProxyUtil{publicstaticStarcreateProxy(Starstar){return(Star)Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(),//参数1newClass?[]{Star.class},//参数2newInvocationHandler(){//参数3OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{if(sing.equals(method.getName())||dance.equals(method.getName())){System.out.println(找演唱会地点);Objectresultmethod.invoke(star,args);System.out.println(收尾);returnresult;}returnmethod.invoke(star,args);}});}}为了让代理对象正常工作Proxy.newProxyInstance必须明确以下三个参数1. 签名publicstaticObjectnewProxyInstance(ClassLoaderloader,Class?[]interfaces,InvocationHandlerh)2. 参数1ClassLoader loader (类加载器)在程序运行过程中动态代理会在内存中实时生成代理类的字节码。为了让 JVM 识别并加载该字节码需要提供一个类加载器。通常使用当前工具类的类加载器ProxyUtil.class.getClassLoader()或被代理类的类加载器。3. 参数2Class?[] interfaces(接口数组)此参数表示代理类要实现哪些接口。在我们的例子中代理要代替明星唱歌跳舞因此需要实现Star接口写为new Class?[]{Star.class}。4. 参数3InvocationHandler h (调用处理器)当外部调用代理对象的任何方法时都会转发到此处理器的invoke方法中执行。3. 测试与运行我们编写Main类进行测试publicclassMain{publicstaticvoidmain(String[]args){// 1. 创建真实对象BigStarbigStarnewBigStar();// 2. 创建代理对象StarproxyStarProxyUtil.createProxy(bigStar);// 3. 调用代理方法StringretproxyStar.sing(Lucky);System.out.println(ret);}}运行后控制台输出如下找演唱会地点 小美正在唱Lucky 收尾 谢谢大家4. 代理字节码原理看看代理对象的伪代码importjava.lang.reflect.InvocationHandler;importjava.lang.reflect.Method;importjava.lang.reflect.Proxy;importjava.lang.reflect.UndeclaredThrowableException;publicfinalclass$Proxy0extendsProxyimplementsStar{privatestaticMethodm1;// 代表 Object.equals()privatestaticMethodm2;// 代表 Object.toString()privatestaticMethodm3;// 代表 Star.sing()privatestaticMethodm4;// 代表 Star.dance()static{try{m1Class.forName(java.lang.Object).getMethod(equals,Object.class);m2Class.forName(java.lang.Object).getMethod(toString);m3Class.forName(Star).getMethod(sing,String.class);m4Class.forName(Star).getMethod(dance);}catch(Exceptione){thrownewNoSuchMethodError(e.getMessage());}}public$Proxy0(InvocationHandlerh){super(h);// 将处理器传递给父类 java.lang.reflect.Proxy}OverridepublicfinalStringsing(StringsongName){try{// 所有方法调用都会转发到超类持有的 InvocationHandler 的 invoke 方法中return(String)super.h.invoke(this,m3,newObject[]{songName});}catch(Error|RuntimeExceptione){throwe;}catch(Throwablet){thrownewUndeclaredThrowableException(t);}}Overridepublicfinalvoiddance(){try{super.h.invoke(this,m4,null);}catch(Error|RuntimeExceptione){throwe;}catch(Throwablet){thrownewUndeclaredThrowableException(t);}}}动态生成的代理类命名为$Proxy0它继承了java.lang.reflect.Proxy并且实现了目标接口Star。Java 不支持多重继承$Proxy0已经占用了继承Proxy的名额。所以只能代理接口无法代理实例化的类.$Proxy0的构造方法接收一个InvocationHandler h并通过super(h)传给父类Proxy统一保管。在重写的接口方法如sing、dance中没有包含任何业务逻辑而是直接调用super.h.invoke(this, method, args).总结动态代理的核心思想是解耦通过代理对象将繁琐的非核心业务与真实对象的核心业务隔离开来。JDK 动态代理利用java.lang.reflect.Proxy类的newProxyInstance方法在运行期动态地在内存中生成实现了指定接口的代理类字节码。代理类如$Proxy0继承自Proxy并实现目标接口其内部持有一个InvocationHandler对象所有接口方法的调用都会被重定向并转发到该处理器的invoke方法中执行。

相关新闻

CMake GUI 3.28.3 与 VS 2019/2022 协同配置:5步解决“project files may be invalid”

CMake GUI 3.28.3 与 VS 2019/2022 协同配置:5步解决“project files may be invalid”

2026/7/13 5:45:47

CMake GUI 3.28.3 与 Visual Studio 协同配置全指南:从报错到生成的完整解决方案最近在Windows平台上使用CMake构建项目时,不少开发者遇到了"Error in configuration process, project files may be invalid"这个令人头疼的错误提示。作为一名…

C++11 随机数生成——告别 rand()

C++11 随机数生成——告别 rand()

2026/7/13 5:45:47

文章目录C11 随机数生成——告别 rand()一、C 语言的 rand() 有什么问题二、C11 的三大组件三、实战例子3.1 模拟温度:42C 上下波动 2C3.2 模拟误码率:极小数值3.3 生成整数范围四、逐行拆解std::random_device{}()std::mt19937 rng{种子}std::uniform_r…

Axure RP 9 动态面板实现无限级树形菜单:3步交互逻辑与变量控制详解

Axure RP 9 动态面板实现无限级树形菜单:3步交互逻辑与变量控制详解

2026/7/13 5:35:46

Axure RP 9 动态面板实现无限级树形菜单:3步交互逻辑与变量控制详解树形菜单作为信息架构可视化的重要组件,在产品原型设计中扮演着关键角色。本文将深入解析如何利用Axure RP 9的动态面板和中继器,构建支持无限层级扩展的智能树形菜单系统。…

3分钟掌握Seraphine:英雄联盟玩家的智能BP与战绩分析神器

3分钟掌握Seraphine:英雄联盟玩家的智能BP与战绩分析神器

2026/7/13 7:35:51

3分钟掌握Seraphine:英雄联盟玩家的智能BP与战绩分析神器 【免费下载链接】Seraphine 英雄联盟战绩查询工具 项目地址: https://gitcode.com/gh_mirrors/se/Seraphine 在英雄联盟排位赛中,你是否曾因BP阶段手忙脚乱而错失先机?是否希望…

2026不容错过!深度测评5款适配多学科的AI论文写作工具,初稿轻松搞定

2026不容错过!深度测评5款适配多学科的AI论文写作工具,初稿轻松搞定

2026/7/13 7:35:51

还在为写期刊论文而感到困扰吗?面对海量的文献、繁琐的格式要求以及反复的修改,低效率已经成为大多数学术人士的共同苦恼!但你无需再烦恼,接下来介绍的这四款AI论文写作工具将帮助你轻松克服这些难题。无论是进行文献检索、生成论…

如何5分钟掌握百度网盘提取码智能查询:baidupankey终极指南

如何5分钟掌握百度网盘提取码智能查询:baidupankey终极指南

2026/7/13 7:35:51

如何5分钟掌握百度网盘提取码智能查询:baidupankey终极指南 【免费下载链接】baidupankey 在线查询网盘提取码(维护中 rm repo) 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 还在为百度网盘资源下载而烦恼吗&#xff1f…

LAV Filters终极指南:5步实现Windows专业级视频播放体验

LAV Filters终极指南:5步实现Windows专业级视频播放体验

2026/7/13 7:35:51

LAV Filters终极指南:5步实现Windows专业级视频播放体验 【免费下载链接】LAVFilters LAV Filters - Open-Source DirectShow Media Splitter and Decoders 项目地址: https://gitcode.com/gh_mirrors/la/LAVFilters 在Windows平台上播放视频时,你…

计量经济学驱动的价格优化实战指南

计量经济学驱动的价格优化实战指南

2026/7/13 7:35:51

1. 项目概述:价格优化不是调价,而是用计量经济学给定价装上导航仪“Econometrics — How to Perform Price Optimization”这个标题乍看像教科书章节名,但在我过去十年帮二十多家零售、SaaS和制造企业落地价格策略的过程中,它实际…

Unity热更新实战:基于HybridCLR与Addressables的完整框架搭建指南

Unity热更新实战:基于HybridCLR与Addressables的完整框架搭建指南

2026/7/13 7:25:51

1. 项目概述:为什么我们需要一个现代化的热更新框架?如果你正在开发一款Unity游戏,尤其是面向移动平台,那么“热更新”这个词对你来说一定不陌生。它不是一个锦上添花的功能,而是一个关乎项目生死存亡的基石。想象一下…

Unity游戏文本翻译架构深度解析:XUnity.AutoTranslator的技术实现与工程实践

Unity游戏文本翻译架构深度解析:XUnity.AutoTranslator的技术实现与工程实践

2026/7/13 7:41:16

Unity游戏文本翻译架构深度解析:XUnity.AutoTranslator的技术实现与工程实践 【免费下载链接】XUnity.AutoTranslator 项目地址: https://gitcode.com/gh_mirrors/xu/XUnity.AutoTranslator XUnity.AutoTranslator作为Unity游戏社区中最成熟的文本翻译解决方…

openEuler Raspberry Pi Kernel设备驱动开发指南:为树莓派硬件添加支持

openEuler Raspberry Pi Kernel设备驱动开发指南:为树莓派硬件添加支持

2026/7/12 0:03:42

openEuler Raspberry Pi Kernel设备驱动开发指南:为树莓派硬件添加支持 【免费下载链接】raspberrypi-kernel It provides openEuler kernel source for Raspberry Pi 项目地址: https://gitcode.com/openeuler/raspberrypi-kernel 前往项目官网免费下载&…

openEuler系统集成测试实战:基于smoke-test套件的环境验证技巧

openEuler系统集成测试实战:基于smoke-test套件的环境验证技巧

2026/7/12 0:03:42

openEuler系统集成测试实战:基于smoke-test套件的环境验证技巧 【免费下载链接】integration-test The repo contains test suits for system integration test 项目地址: https://gitcode.com/openeuler/integration-test 前往项目官网免费下载:…

卡梅德生物技术快报|纯化重组蛋白:变异链球菌 SepM 截短蛋白载体构建、诱导优化与纯化重组蛋白全套参数方案

卡梅德生物技术快报|纯化重组蛋白:变异链球菌 SepM 截短蛋白载体构建、诱导优化与纯化重组蛋白全套参数方案

2026/7/13 0:05:25

1 研究背景与现存技术痛点(提出问题)在口腔微生物分子机制研究中,SepM 蛋白酶是调控变异链球菌群体感应、致龋菌素合成的核心功能蛋白,体外功能验证、抗体开发均依赖高纯度可溶性 SepM 蛋白。当前原核表达体系针对 SepM 存在三大技…

卡梅德生物技术快报|重组蛋白的表达和纯化:IMAC 金属螯合色谱全流程工艺手册|基质 - 配基 - 金属离子匹配与蛋白质分离纯化参数优化

卡梅德生物技术快报|重组蛋白的表达和纯化:IMAC 金属螯合色谱全流程工艺手册|基质 - 配基 - 金属离子匹配与蛋白质分离纯化参数优化

2026/7/13 0:05:25

1 研究背景与现存技术痛点(提出问题)基因工程、蛋白质组学、生物制药研发流程中,蛋白质分离纯化是决定下游实验成败的关键环节。当前实验室常规蛋白质分离纯化工艺存在三类难以标准化的技术瓶颈:传统离子交换、分子筛层析无特异性…

卡梅德生物技术快报|蛋白质分离纯化:肠激酶可溶性原核表达 + 两步层析全参数|标准化蛋白质分离纯化 SOP

卡梅德生物技术快报|蛋白质分离纯化:肠激酶可溶性原核表达 + 两步层析全参数|标准化蛋白质分离纯化 SOP

2026/7/13 0:05:25

研究痛点提出(提出问题)重组肠激酶是融合标签切除核心工具酶,当前原核表达体系存在三大标准化难题,直接阻碍可复现的蛋白质分离纯化流程搭建:Trx、GST、单 SUMO 标签融合产物绝大多数为包涵体,沉淀占比超 9…