(十七)关于动态代理,你能说出动态代理的几种方式?

简介: 动态代理是指代理类不是写在代码中的,而是在代码运行过程中产生的,Java提供了两种方式来实现动态代理,分别是基于Jdk的动态代理和基于Cglib的动态代理。

微信搜索《Java鱼仔》,每天一个知识点不错过


(一)每天一个知识点


关于动态代理,你能说出动态代理的几种方式?


(二)详解


动态代理是指代理类不是写在代码中的,而是在代码运行过程中产生的,Java提供了两种方式来实现动态代理,分别是基于Jdk的动态代理和基于Cglib的动态代理。


2.1 基于Jdk的动态代理


首先我们来搭建一套实现动态代理的实现,以租房为例,我新建一个租房的接口:


publicinterfaceRoom {
voidrent();
}

然后下一个实际的租房实现类


publicclassRealRoomimplementsRoom {
privateStringroomname;
publicRealRoom(Stringroomname) {
this.roomname=roomname;
    }
publicvoidrent() {
System.out.println("租了"+roomname);
    }
}

基于Jdk的动态代理核心在于InvocationHandler 接口,首先我们新建一个类ProxyHandler来实现这个InvocationHandler 接口,并实现里面的invoke方法


publicclassProxyHandlerimplementsInvocationHandler {
Objectobject;
publicProxyHandler(Objectobject) {
this.object=object;
    }
//proxy 代理对象//method 要实现的方法//args 方法的参数    publicObjectinvoke(Objectproxy, Methodmethod, Object[] args) throwsThrowable {
System.out.println("代理执行之前:"+method.getName());
Objectinvoke=method.invoke(object, args);
System.out.println("代理执行之后:"+method.getName());
returninvoke;
    }
}

InvocationHandler 是一个接口,每个代理的实例都有一个与之关联的

InvocationHandler 实现类,如果代理的方法被调用,那么代理便会通知和转发给内部的 InvocationHandler 实现类invoke,由它实现处理内容。


接下来写一个方法来实现动态代理


publicstaticvoidmain(String[] args) {
Roomroom=newRealRoom("碧桂园");
//obj.getClass().getClassLoader()类加载器//obj.getClass().getInterfaces() 目标类实现的接口//InvocationHandler对象InvocationHandlerinvocationHandler=newProxyHandler(room);
RoomproxyRoom= (Room) Proxy.newProxyInstance(room.getClass().getClassLoader(), room.getClass().getInterfaces(), invocationHandler);
proxyRoom.rent();
}

这段代码的另外一个核心是Proxy.newProxyInstance,该方法需要三个参数,目的是运行期间生成代理类,每个参数的功能已经写在了注释中。这段代码的意思就是Proxy 动态产生的代理对象会调用 InvocationHandler 实现类invoke。


最终我们不需要RealRoom去调用rent方法,通过代理类就可以实现这个rent方法。


最后结果如下:


代理执行之前:rent租了碧桂园代理执行之后:rent

运行时就会在控制台上打印出来,这也是Spring AOP的核心


JDK动态代理类实现了InvocationHandler接口,重写的invoke方法。


JDK动态代理的基础是反射机制(method.invoke(对象,参数))


Proxy.newProxyInstance()


2.2 基于Cglib的动态代理


基于Jdk的动态代理局限性在于代理的类必须要实现接口,而基于CGlib的动态代理则没有这个限制:


搭建CGlib环境我们首先要引入一个CGlib的jar包:



<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>2.2.2</version></dependency>

此时我们不再需要接口,直接新建一个CGRoom类:


publicclassCGRoom {
publicvoidrent(StringroomName){
System.out.println("租了"+roomName);
    }
}

CGlib实现动态代理的核心在于MethodInterceptor接口:


publicclassMyMethodInterceptorimplementsMethodInterceptor {
@OverridepublicObjectintercept(Objecto, Methodmethod, Object[] objects, MethodProxymethodProxy) throwsThrowable {
System.out.println("代理执行之前:"+method.getName());
Objectobject=methodProxy.invokeSuper(o,objects);
System.out.println("代理执行之后:"+method.getName());
returnobject;
    }

这个接口只有一个intercept()方法,拦截被代理对象,这个方法有4个参数:


1)表示增强的对象,即实现这个接口类的一个对象;


2)表示要被拦截的方法;


3)表示要被拦截方法的参数;


4)表示要触发父类的方法对象;


最后生成代理类对象并输出执行结果


publicstaticvoidmain(String[] args) {
//创建Enhancer对象,类似于JDK动态代理的Proxy类,下一步就是设置几个参数Enhancerenhancer=newEnhancer();
//设置目标类的字节码文件enhancer.setSuperclass(CGRoom.class);
//设置回调函数enhancer.setCallback(newMyMethodInterceptor());
//创建代理对象CGRoomproxy= (CGRoom) enhancer.create();
proxy.rent("碧桂园");
}

运行结果:


代理执行之前:rent租了碧桂园代理执行之后:rent


(三)总结


两种代理方式各有优劣,在使用方面,JDK动态代理只能基于接口进行实现,而CGLIb对代理的目标对象无限制,无需实现接口。


在依赖方面,Java原生支持JDK动态代理,而CGlib的实现还需要引入相关依赖包。

相关文章
|
6天前
|
存储 弹性计算 人工智能
【2025云栖精华内容】 打造持续领先,全球覆盖的澎湃算力底座——通用计算产品发布与行业实践专场回顾
2025年9月24日,阿里云弹性计算团队多位产品、技术专家及服务器团队技术专家共同在【2025云栖大会】现场带来了《通用计算产品发布与行业实践》的专场论坛,本论坛聚焦弹性计算多款通用算力产品发布。同时,ECS云服务器安全能力、资源售卖模式、计算AI助手等用户体验关键环节也宣布升级,让用云更简单、更智能。海尔三翼鸟云服务负责人刘建锋先生作为特邀嘉宾,莅临现场分享了关于阿里云ECS g9i推动AIoT平台的场景落地实践。
【2025云栖精华内容】 打造持续领先,全球覆盖的澎湃算力底座——通用计算产品发布与行业实践专场回顾
|
5天前
|
云安全 人工智能 自然语言处理
阿里云x硅基流动:AI安全护栏助力构建可信模型生态
阿里云AI安全护栏:大模型的“智能过滤系统”。
|
5天前
|
人工智能 自然语言处理 自动驾驶
关于举办首届全国大学生“启真问智”人工智能模型&智能体大赛决赛的通知
关于举办首届全国大学生“启真问智”人工智能模型&智能体大赛决赛的通知
|
Linux 虚拟化 iOS开发
VMware Workstation Pro 25H2 for Windows & Linux - 领先的免费桌面虚拟化软件
VMware Workstation Pro 25H2 for Windows & Linux - 领先的免费桌面虚拟化软件
1088 4
|
8天前
|
存储 机器学习/深度学习 人工智能
大模型微调技术:LoRA原理与实践
本文深入解析大语言模型微调中的关键技术——低秩自适应(LoRA)。通过分析全参数微调的计算瓶颈,详细阐述LoRA的数学原理、实现机制和优势特点。文章包含完整的PyTorch实现代码、性能对比实验以及实际应用场景,为开发者提供高效微调大模型的实践指南。
688 2
|
6天前
|
编解码 自然语言处理 文字识别
Qwen3-VL再添丁!4B/8B Dense模型开源,更轻量,仍强大
凌晨,Qwen3-VL系列再添新成员——Dense架构的Qwen3-VL-8B、Qwen3-VL-4B 模型,本地部署友好,并完整保留了Qwen3-VL的全部表现,评测指标表现优秀。
520 7
Qwen3-VL再添丁!4B/8B Dense模型开源,更轻量,仍强大
|
7天前
|
JavaScript API 开发工具
如何在原生App中调用Uniapp的原生功能?
如何在原生App中调用Uniapp的原生功能?
333 139