JDK动态代理为什么必须用接口

JDK动态代理为什么必须要基于接口 目录1. 前言2. 一个简单的例子2.1. 定义接口2.2. 接口实现类2.3. 自定义 `Handler`2.4. 测试2.5. 输出结果 1. 前言 JDK 动态代理的应用还是非常广泛的,例如在 Spring、MyBatis 以及 Feign 等很多框架中动态代理都被大量的使用,可以说学好 JDK 动态代理,对于我们阅读这些框架的底层源码还是很有帮助的 2. 一个简单的例子 在分析原因之前,我们先完整的看一下实现 JDK 动态代理需要几个步骤,首先需要定义一个接口 2.1. 定义接口 public in 阅读详情


JDK动态代理为什么必须用接口

JDK动态代理与CGLIB动态代理。从Spring的AOP框架介绍中得知对于使用接口的类,Spring使用JDK动态代理,没有接口的就使用别的AOP框架aspectj,但这些都是依赖于Java字节码工具ASM生成一个原类的新类,调用Callback 。

但是JDK动态代理为什么必须使用接口呢,难道原理不是像ASM一样修改字节码吗?带着这个疑问,开始看JDK的Proxy代码。

使用JDK动态代理时,会使用Proxy的newProxyInstance方法;
从创建代理函数看起,即
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException ,

通过源码可以看到,这个类第一步生成一个代理类(注意,这里的参数就是接口列表),
Class cl = getProxyClass(loader, interfaces);

然后通过代理类找到构造参数为InvocationHandler的构造函数并生成一个新类。
Constructor cons = cl.getConstructor(constructorParams);//这个有用,在后面细说
return (Object) cons.newInstance(new Object[] { h }); 

接口起什么作用呢,这要看getProxyClass方法的代码,这个源码很长,大致分为三段:
第一:验证
第二:缓存创建新类的结构,如果创建过,则直接返回。(注意:这里的KEY就是接口列表)
第三:如果没有创建过,则创建新类

创建代码如下
    long num;
   //获得代理类数字标识
   synchronized (nextUniqueNumberLock) {
     num = nextUniqueNumber++;
    }
    //获得创建新类的类名$Proxy,包名为接口包名,但需要注意的是,如果有两个接口而且不在同一个包下,也会报错
    String proxyName = proxyPkg + proxyClassNamePrefix + num;
    //调用class处理文件生成类的字节码,根据接口列表创建一个新类,这个类为代理类,
    byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces);
    //通过JNI接口,将Class字节码文件定义一个新类
     proxyClass = defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length);

根据前面的代码Constructor cons = cl.getConstructor(constructorParams);
可以猜测到接口创建的新类proxyClassFile 不管采用什么接口,都是以下结构
public class $Proxy1 extends Proxy implements 传入的接口{ }
生成新类的看不到源代码,不过猜测它的执行原理很有可能是如果类是Proxy的子类,则调用InvocationHandler进行方法的Invoke

JDK动态代理的原理是根据定义好的规则,用传入的接口创建一个新类,这就是为什么采用动态代理时为什么只能用接口引用指向代理,而不能用传入的类引用执行动态类。


获取的代理实例无法强制转换为实现类,会抛出类强制转换异常;
接口定义的方法互相调用不会调用到InvocationHandler的invoke方法,即无法实现嵌套代理;

面试官:解释下JDK动态代理为什么要基于接口? 我们知道,扩展一个类,要么继承,要么实现接口,这两种方式都可以对方法进行增强。JDK 动态代理使用的是类和接口。在动态代理机制中,Proxy类通过实现代理类的接口来生成代理对象,并将方法调用委托给。因此,JDK 动态代理的工作原理也决定了它只能代理接口,而不能直接代理具体类。那么可以有其他方式不代理接口吗,有,就是CGLIB动态代理! 阅读详情

相关推荐

SAP采购订单行项目增强实战:用BADI ME_GUI_PO_CUST添加自定义字段(避坑指南)

本文详细解析了如何通过BADI ME_GUI_PO_CUST在SAP采购订单行项目中添加自定义字段,包括技术架构理解、字段扩展步骤、自定义函数组创建及BADI实现。文章特别强调了避开官方文档未提及的陷阱,如字段映射限制和屏幕显示问题,并提供了高级优化技巧和性能建议。

weixin_30402343的博客 593

代理模式—基于JDK(接口)的动态代理的使用方法

代理模式就是给对象提供一种代理对象去控制对该对象的访问,代理类与委托类有同样的接口,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。相当显示生活中的:外卖、房产中介代理模式在访问实际对象时引入一定程度的间接性,可以做到(低耦合性,高扩展性)

morningthesoda的博客 309

LT9211 单路mipi转双路mipi芯片,方案成熟,提供技术支持

LT9211 单路mipi转双路mipi芯片

TEL15012949045的博客 5012

java代理模式之jdk动态代理详解(超详细)

代理模式: 代理是基本的设计模式之一,它为你提供额外的或者不同的操作,而插入的用来代理"实际"对象的对象.这些操作通常涉及与"实际"对象的通信,因此代理通常充当着中间人的角色. 动态代理 动态代理是在实现阶段不用关心代理类,而在运行阶段才指定哪一个对象. 动态代理的优点: 职责清晰 真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件完成事务,附带的结果就是编程简...

及时雨的csdn 3155

Ubuntu20.04配置PX4环境启动或编译jmavsim 出现的错误及解决办法

错误1:ant命令未找到

Iamsonice的博客 8855

ESD镜像解密与转换全攻略:从esd-decrypter到WinNTSetup的完整流程

本文详细解析了ESD镜像的加密特性与压缩优势,并提供了从解密到转换的完整实战指南。核心步骤包括使用esd-decrypter工具解密ESD文件为WIM格式,以及如何结合WinNTSetup进行灵活的系统安装或进一步封装为可引导的ISO镜像,帮助用户高效处理官方Windows安装镜像。

weixin_29207439的博客 447

为什么JDK动态代理只能代理接口?

为什么JDK动态代理只能代理接口?

LINgZone2的博客 1678

[南大ICS]PA1 - 开天辟地的篇章: 最简单的计算机

task PA1.1: 实现单步执行, 打印寄存器状态, 扫描内存 task PA1.2: 实现算术表达式求值 task PA1.3: 实现所有要求, 提交完整的实验报告

qq_42474104的博客 1570

JDK 的动态代理

JDK的动态代理是一种通过Java的反射机制实现的代理方式。这种方式实现了动态代理的功能,可以在目标方法调用前后进行一些额外的操作。定义接口:首先需要定义一个接口,该接口是被代理类和代理类共同实现的接口。方法中,我们可以编写与方法调用相关的逻辑,例如前置增强、后置增强等。创建被代理对象:创建一个实现了接口的原始类,也就是被代理类。方法中,可以编写在方法调用前后进行的额外操作。调用代理对象:使用生成的代理对象来调用目标方法。当调用代理对象的方法时,实际上是通过代理对象的。方法的执行会触发代理类的。

weixin_43669384的博客 770

直线电机驱动技术原理与应用解析

直线电机作为直接电能-直线运动转换装置,其核心原理基于电磁感应定律和洛伦兹力公式。通过三相交流电在定子绕组中产生行波磁场,与动子永磁体相互作用实现精准推力控制。相比传统旋转电机传动系统,直线电机具有零传动间隙、高动态响应(加速度可达10g)和微米级定位精度等技术优势,这使其成为半导体光刻机、精密数控机床等高端装备的关键驱动部件。现代直线电机驱动单元通常采用三环控制架构(电流环、速度环、位置环),配合SiC功率器件和高分辨率光栅反馈,实现纳米级运动控制。随着模块化设计和直接冷却技术的发展,直线电机正朝着更高功

weixin_26802933的博客 259

AE(自动曝光)调试策略:曝光曲线设计与过曝控制

自动曝光(AE, Auto Exposure)系统是图像质量控制链路中的核心模块之一,其性能直接决定了成像亮度是否稳定、细节是否完整、场景切换是否自然。在现代移动终端影像系统中,AE 不仅需要适应不同光照强度和复杂环境,还需兼顾人脸优先、HDR触发、视频帧率控制等多目标优化需求。本文基于高通 Snapdragon 和 MTK Dimensity 等主流平台的调试经验,系统梳理了 AE 模型设计原则、曝光曲线配置、测光策略选择与过曝抑制机制,并结合典型实战案例,提供可复制的工程落地路径。

努力分享一些人工智能、计算机视觉、影像等相关的知识干货! 3089

JDK动态代理为什么必须要基于接口?

原创:微信公众号 码农参上,欢迎分享,转载请保留出处。 前几天的时候,交流群里的小伙伴抛出了一个问题,为什么JDK的动态代理一定要基于接口实现呢? 好的安排,其实要想弄懂这个问题还是需要一些关于代理和反射的底层知识的,我们今天就盘一盘这个问题,走你~ 一个简单的例子 在分析原因之前,我们先完整的看一下实现jdk动态代理需要几个步骤,首先需要定义一个接口: public interface Worker { void work(); } 再写一个基于这个接口的实现类: public class .

4724

预编码算法(个人总结)

预编码算法是无线通信系统中的关键技术,通过在发送端对信号进行处理,可以有效减少干扰,提高系统性能。预编码算法在5G、Wi-Fi、卫星通信等领域具有广泛的应用前景,同时,随着深度学习、大规模MIMO和物理层安全等技术的发展,预编码算法的研究将进一步推动无线通信技术的发展。CSI的准确性直接影响到预编码的效果。预编码是一种在发送端对信号进行线性变换的技术,以优化信号的空间分布,使得接收端能够更好地接收和解码信号。预编码算法,特别是基于矩阵分解的预编码算法,计算复杂度较高,限制了其在实际系统中的应用。

年糕的博客 5287

JDK动态代理为什么只能代理有接口的类?

之所以要传入接口,不能传入类,还是取决于 JDK动态代理的底层实现(如图)。 JDK动态代理会在程序运行期间动态生成一个代理类$Proxy0,这个动态生成的代理类会继承java.lang.reflect.Proxy类,同时还会实现被代理类的接口 IHelloService。 在 Java中,是不支持多重继承的。而每个动态代理类都会继承 Proxy类(这也是 JDK动态代理的实现规范),所以就导致 JDK里面的动态代理只能代理接口,而不能代理实现类。 就下面这张图,简单来说,他已经继承了Proxy类,那

qq_62097431的博客 1962

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

JDK动态代理为什么需要接口?

回答这个问题之前需要首先由JDK动态代理的基础,可以查看大佬写的这篇文章:Java JDK 动态代理(AOP)使用及实现原理分析,然后再来深入思考这个问题。 还有一点,需要特别注意的是,当我们在介绍静态代理的时候,都知道需要被代理的类和代理的类都需要实现同一个接口,这样才能完成静态代理,关于静态代理的内容上面的那篇博客也介绍了,这里只是提一下这个点。 关于JDK动态代理准确的说是对接口进行的代理,创建一个该接口的子类,这个重点突出的是这个接口,而不是某个类需要...

qq_35634181的博客 1730

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

jdk的动态代理及为什么需要接口

动态代理有关,无非是使用JDK动态代理,和cglib动态代理。一直不待明白的是为什么,jdk的动态代理需要接口才能实现,这也是其短板和令人诟病的地方。很多的博文说的很复杂,代码一大堆,没有太明白。手打了一下,参考了一些优秀的博文,在这里给自己做个总结。 首先,动态代理是个挺有用的东西,常见的就是javaAOP的有关,主要的作用是是在一个方法使用前后,能进行别的处理。比如吧,aop所说的,面向切面...

zxysshgood的博客 1万+

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

【动态代理】JDK动态代理为什么要基于接口

我们都知道CGLIB动态代理是基于继承的,而JDK动态代理是基于接口的,为什么不能也基于继承呢?现在通过代码来看看原因,至于面试的时候可能会被问到为什么不通过聚合或者组合来实现,原因很明显就是为了降低耦合性。 // 定义目标对象的接口 public interface UserDao { /** * */ void query(); } // 目标对象 @Repository("userDao") public class UserDaoImpl implements UserDao { @

hansirl的博客 852

JDK动态代理为什么必须针对接口

JDK动态代理为什么必须针对接口?其与CGLIB的对比 示例代码: public interface AopService {   public void doService(); } public class AopServiceImpl implements AopService { private String singal; public Strin

zanglianggo的博客 7196

jdk动态代理为什么必须是基于接口实现的?

因为jdk动态代理生成的class文件已经继承了Proxy,而java是单继承的,所以是基于jdk动态代理是基于接口的。 请看代码使用jdk动态代理生成class文件 public static void main(String[] args) { Class<?>[] interfaces = new Class[]{Dao.class} ;// Dao是一个自己定义...

qq_35016215的博客 3365

JDK动态代理为什么只能代理有接口的类

JDK动态代理为什么只能代理有接口的类 为什么只能代理有接口的类? 是因为JDK动态代理本身机制决定的,首先在java里面动态代理是Proxy.newProxyInstance()这个方法来实现的,它需要传入被动态代理的一个接口类,还是取决于JDK动态代理的的一个底层实现,JDK动态代理会在程序运行期间,去动态生产一个代理类,叫$ProxyO,那么这个动态生成的代理类会去继承一个java.lang.reflect.Proxy这样一个类,同时还会去实现被代理类的接口,在java里面不支持多种继承的,而每个动

huangqingfeng的博客 4810

JDK动态代理原理:为什么目标对象一定要实现接口?

JDK动态代理、Proxy.newProxyInstance、InvocationHandler、目标对象一定要实现接口、Proxy类

weixin_45967584的博客 3154

JDK动态代理入门、JDK动态代理原理、为什么JDK动态代理是基于接口的

动态代理 JDK动态代理 JDK动态代理 只能 代理接口;CGLIB动态代理可以代理类; 静态代理缺点 当接口增删改方法,那么代理类已得要跟着修改; 代理类的每个接口对象对应一个委托对象,如果委托对象很多,代理类就会变得异常臃肿 https://www.jianshu.com/p/85d181d7d09a 定义委托对象接口 public interface Subject { void test(); } 委托对象接口实现类 public class RealSubject impleme

qq_43369986的博客 794
上一篇: Spring获取bean的几种方式
下一篇: CGlib无入侵代理入门使用
架构师的清醒
博客等级 码龄14年 291粉丝 397原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值