动态代理:面向接口编程,屏蔽RPC处理过程
RPC远程调用
使用 RPC 时,一般的做法是先找服务提供方要接口,通过 Maven把接口依赖到项目中。在编写业务逻辑的时候,如果要调用提供方的接口,只需要通过依赖注入的方式把接口注入到项目中,然后在代码里面直接调用接口的方法 。
接口里并不会包含真实的业务逻辑,业务逻辑都在服务提供方。
核心技术:动态代理。
RPC 会自动给接口生成一个代理类,项目中注入接口的时候,运行过程中实际绑定的是这个接口生成的代理类。在接口方法被调用的时候,实际上是被生成代理类拦截到,这样就可以在生成的代理类里面,加入远程调用逻辑。
流程如下:

实现原理
jdk动态代理:
/*** 要代理的接口*/
public interface Hello {String say();
}/*** 真实调用对象*/
public class RealHello {public String haha(){return "i'm proxy";}
}
代理类实现InvocationHandler接口
/*** JDK代理类生成*/
public class JDKProxy implements InvocationHandler {private Object target;JDKProxy(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] paramValues) {return ((RealHello)target).haha();}
}public class TestProxy {public static void main(String[] args){// 构建代理器JDKProxy proxy = new JDKProxy(new RealHello());ClassLoader classLoader = Hello.class.getClassLoader();// 把生成的代理类保存到文件
System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles","true");// 生成代理类Hello test = (Hello) Proxy.newProxyInstance(classLoader, new Class[]{Hello.class}, proxy);// 方法调用System.out.println(test.say());}
}
解释:给 Hello 接口生成一个动态代理类,并调用接口 say() 方法,但真实返回的值是来自 RealHello 里面的 haha() 方法返回值。
重点是代理类的生成,Proxy.newProxyInstance。
参数 saveGeneratedFiles 来控制是否把生成的字节码保存到本地磁盘。
key为“sun.misc.ProxyGenerator.saveGeneratedFiles”的Property来控制的,动态生成的类会保存在工程根目录下的 com/sun/proxy 目录里面。
生成的代理类。

package com.sun.proxy;import com.lkl.proxy.Hello;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;public final class $Proxy0 extends Proxy implements Hello {private static Method m1;private static Method m2;private static Method m3;private static Method m0;public $Proxy0(InvocationHandler var1) throws {super(var1);}public final boolean equals(Object var1) throws {try {return (Boolean)super.h.invoke(this, m1, new Object[]{var1});} catch (RuntimeException | Error var3) {throw var3;} catch (Throwable var4) {throw new UndeclaredThrowableException(var4);}}public final String toString() throws {try {return (String)super.h.invoke(this, m2, (Object[])null);} catch (RuntimeException | Error var2) {throw var2;} catch (Throwable var3) {throw new UndeclaredThrowableException(var3);}}public final String say() throws {try {// 代理类执行return (String)super.h.invoke(this, m3, (Object[])null);} catch (RuntimeException | Error var2) {throw var2;} catch (Throwable var3) {throw new UndeclaredThrowableException(var3);}}public final int hashCode() throws {try {return (Integer)super.h.invoke(this, m0, (Object[])null);} catch (RuntimeException | Error var2) {throw var2;} catch (Throwable var3) {throw new UndeclaredThrowableException(var3);}}static {try {m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));m2 = Class.forName("java.lang.Object").getMethod("toString");m3 = Class.forName("com.lkl.proxy.Hello").getMethod("say");m0 = Class.forName("java.lang.Object").getMethod("hashCode");} catch (NoSuchMethodException var2) {throw new NoSuchMethodError(var2.getMessage());} catch (ClassNotFoundException var3) {throw new NoClassDefFoundError(var3.getMessage());}}
}
$Proxy0 类里面有一个跟 Hello 一样签名的 say() 方法,其中 this.h 绑定的是刚才传入的 JDKProxy 对象,所以当调用 Hello.say() 的时候,实际被转发到了JDKProxy.invoke()。
单纯从代理功能上来看,JDK 默认的代理功能是有一定的局限性的,要求被代理的只能是接口。原因是生成的代理类会继承 Proxy 类,但Java不支持多重继承。
JDK默认的代理功能,最大的问题就是性能问题。生成后的代理类是使用反射来完成方法调用,而这种方式相对直接用编码调用来说,性能会降低,但JDK8及以上版本对反射调用的性能有很大的提升。
除了JDK 默认的nvocationHandler能完成代理功能,还有很多其他的第三方框架也可以实现,比如Javassist、Byte Buddy 这样的框架。
Javassist定位是能够操纵底层字节码,要生成动态代理类比较复杂。但是,通过Javassist生成字节码,不需要通过反射完成方法调用,所以性能会高一些。问题:通过Javassist生成一个代理类后,此 CtClass 对象会被冻结起来,不允许再修改;否则,再次生成时会报错。
Byte Buddy提供了更容易操作的API,编写的代码可读性更高。并且生成的代理类执行速度比Javassist更快。
动态代理框架选型
三个角度考虑:
- 代理类是在运行中生成的,那么代理框架生成代理类的速度、生成代理类的字节码大小等等,都会影响到其性能——生成的字节码越小,运行所占资源就越小。
- 生成的代理类,是用于接口方法请求拦截的,所以每次调用接口方法的时候,都会执行生成的代理类,生成的代理类的执行效率就需要很高效。
- 从使用角度出发的,选择使用起来很方便、好上手的代理类框架。
相关文章:
动态代理:面向接口编程,屏蔽RPC处理过程
RPC远程调用 使用 RPC 时,一般的做法是先找服务提供方要接口,通过 Maven把接口依赖到项目中。在编写业务逻辑的时候,如果要调用提供方的接口,只需要通过依赖注入的方式把接口注入到项目中,然后在代码里面直接调用接口…...
HTTP 405 Method Not Allowed:解析与解决
HTTP 405 Method Not Allowed:解析与解决 引言 在Web开发中,HTTP状态码是服务器与客户端之间通信的重要组成部分。当我们使用Python进行网络请求时,经常会遇到各种HTTP状态码。其中,HTTP 405 “Method Not Allowed” 错误是一个…...
推荐一款CAD/CAM设计辅助工具:Mastercam
Mastercam是一款非常好用的软件,我们的这款软件是由美国CNC软件公司开发,集平面制图、三维设计、曲面设计、数 控编程、刀具处理等多项强大功能于一体。软件的使用过程具有非常直观的特点,用户可以很方便地对自己的作品进行设计。 Mastercam不…...
位运算刷题记录
1. 使两个整数相等的位更改次数 3226. 使两个整数相等的位更改次数 给你两个正整数 n 和 k。 你可以选择 n 的 二进制表示 中任意一个值为 1 的位,并将其改为 0。 返回使得 n 等于 k 所需要的更改次数。如果无法实现,返回 -1。 class Solution {pub…...
爬虫技术——小白入狱案例
知孤云出岫 目录 1. 案例概述2. 案例需求分析3. 实现步骤Step 1: 环境准备Step 2: 分析百度图片URL请求规律Step 3: 编写爬虫代码代码解析 4. 运行代码5. 注意事项6. 案例总结 要实现大批量爬取百度图片,可以使用Python编写一个网络爬虫,通过发送HTTP请求…...
vue 果蔬识别系统百度AI识别vue+springboot java开发、elementui+ echarts+ vant开发
编号:R03-果蔬识别系统 简介:vuespringboot百度AI实现的果蔬识别系统 版本:2025版 视频介绍: vuespringboot百度AI实现的果蔬识别系统前后端java开发,百度识别,带H5移动端,mysql数据库可视化 1 …...
全新更新!Fastreport.NET 2025.1版本发布,提升报告开发体验
在.NET 2025.1版本中,我们带来了巨大的期待功能,进一步简化了报告模板的开发过程。新功能包括通过添加链接报告页面、异步报告准备、HTML段落旋转、代码文本编辑器中的文本搜索、WebReport图像导出等,大幅提升用户体验。 FastReport .NET 是…...
信息学科平台系统设计与实现:Spring Boot技术手册
5系统详细实现 5.1 用户信息管理 基于保密信息学科平台系统的系统管理员可以对用户信息查询。具体界面的展示如图5.1所示。 图5.1 用户信息管理界面 5.2 教师信息管理 管理员可以对教师信息进行查下和删除。具体界面如图5.2所示。 图5.2 教师信息界面 5.3 学科动态管理 管理…...
conda下jupyterlab安装问题以及交互绘图问题记录
安装 1. 直接conda install jupyterlab就好,只要在base环境下安装就行,可以在任意环境下执行jupyter lab启动。 2. 打开jupyter lab后显示Could not determine jupyterlab build status without nodejs,可以执行conda install nodejs安装no…...
尚硅谷react教程_扩展_setState更新状态的2种写法
1.setState setState更新状态的2种写法(1).setState(stateChange,[callback])----对象式的setState1.stateChange为状态改变对象(该对象可以体现出状态的更改)2.callback是可选的回调函数,它在状态更新完毕、界面也更新…...
C语言编写的自动取款机模拟程序
#include〈stdio。h> #include<string。h> #include <stdio.h> #include〈stdlib.h〉 #include〈direct.h〉 #include<io.h> #include 〈errno。h> /********************************************************…...
【常用数据结构】开发中常用的数据结构?
开发中常用的数据结构包括数组、链表、栈、队列、树、图、堆和散列表(哈希表)。这些数据结构在软件开发中有着广泛的应用,并且各自具有独特的特点和用途。 数组 数组是最基本的数据结构之一,用于在内存中连续存储多个元素。数…...
OCC 点云
OCC的基础知识可能还是要系统学习一下,部分导入的模型面类型是很多面都是GeomAbs_BSplineSurface,最终获取参数都要拟合一下,拟合后的生成的面对象没有大小,比如平面只有矢量(大小没有思路) 圆柱拟合面没有…...
方法重写与方法重载
1. 方法重载与方法重写的定义 方法重写(Overriding) 方法重写(Overriding)是指在子类中重新定义与父类中相同的方法。此操作允许子类提供特定的实现,以替代父类的实现。方法重写是实现多态性(Polymorphis…...
Vue3实现地球上加载柱体
最终效果为上图。 实现该技术,需要一些技术,我分别罗列一下: canvas:需要使用canvas根据json来绘制地球,不懂的可以看这篇canvas绘制地球 threejs:需要会使用threejs,这里并没有使用shader&am…...
OpenGL入门003——使用Factory设计模式简化渲染流程
前面两节已经学会了如何使用opengl创建窗口并绘制三角形,我们可以看出有些步骤是固定的,而且都写在main.cpp,这一节我们将了解如何使用Factroy设计模型。将模型渲染逻辑封装在一个单独的类中,简化开发流程,且提高代码复…...
01_AI编程案例展示:借助AI轻松爬取海量网盘链接
爬虫案例展示 今天,我们将展示如何利用AI快速开发一个网络爬虫, 使用的工具是Python和Claude 3.5 Sonnet(国内可用豆包替代) 我们的目标是爬取panhub.fun网站上的夸克网盘链接, 即使你是编程新手,也可以轻松完成这样的任务。 案例1-批量爬取panhub网盘整合包 下…...
【机器学习导引】ch5-神经网络
Q&A 1x1 卷积层在深度学习中的作用? 1x1 卷积层在深度学习中具有几个重要的作用: 通道压缩:1x1卷积可以通过调整输出通道数来减少特征图的深度,从而降低计算成本和参数数量。这有助于在保持特征的情况下简化模型。特征融合&am…...
【Axure原型分享】颜色选择器——填充颜色
今天和大家分享颜色选择器——填充颜色的原型模板,点击颜色区域可以弹出颜色选择器,点击可以选择对应颜色,颜色区域会变色我们选择的颜色,具体效果可以观看下方视频或者打开预览地址体验。 【原型效果】 【Axure高保真原型】颜色…...
怎么安装行星减速电机才是正确的
行星减速电机由于其高效、精密的传动能力,广泛应用于自动化设备、机器人、机床以及其他需要精准控制的领域。正确的安装行星减速电机对于确保设备的性能与延长使用寿命至关重要。 一、前期准备 在进行行星减速电机的安装之前,必须做好充分的前期准备工作…...
CH348芯片全平台驱动实战:从Windows Server到树莓派Linux,一次搞定8串口配置
CH348芯片全平台驱动实战:从Windows Server到树莓派Linux,一次搞定8串口配置 工业自动化、物联网网关、多设备调试等场景中,工程师常面临一个核心痛点:如何在各类操作系统环境下高效管理多串口设备。南京沁恒微电子的CH348芯片以其…...
OpenHarmony与嵌入式Linux实战:从社区项目到深度开发指南
1. 项目概述:从社区精选到深度解析每周浏览技术社区,总能看到不少让人眼前一亮的项目分享,但信息往往比较零散,像是“嵌入式学习资料包”、“OpenHarmony挑战赛作品赏析”这类帖子,标题很吸引人,点进去却常…...
Win11家庭版隐藏功能解锁:除了gpedit.msc,这些高级设置你也能用了
Win11家庭版隐藏功能深度解锁:从组策略到系统优化的高阶玩法 当你第一次在Win11家庭版中成功唤出组策略编辑器(gpedit.msc)时,面对密密麻麻的策略项是否感到无从下手?这就像拿到了一把万能钥匙,却不知道哪些…...
还在为Linux文件搜索太慢而烦恼?FSearch让文件秒级定位成为现实
还在为Linux文件搜索太慢而烦恼?FSearch让文件秒级定位成为现实 【免费下载链接】fsearch A fast file search utility for Unix-like systems based on GTK3 项目地址: https://gitcode.com/gh_mirrors/fs/fsearch 你是否曾在Linux系统中花费大量时间寻找一…...
409.最长回文串(数学算法)
题目 给定一个包含大写字母和小写字母的字符串 s ,返回 通过这些字母构造成的 最长的 回文串 的长度。 在构造过程中,请注意 区分大小写 。比如 "Aa" 不能当做一个回文字符串。 题目链接如下: https://leetcode.cn/problems/longe…...
内网边界安全管控:访问权限隔离与入侵阻断方案
内网边界安全管控的核心目标内网边界安全的核心在于实现访问权限的精细化隔离与实时入侵阻断,需结合网络架构设计、技术工具和流程管理三方面协同实施。访问权限隔离方案网络分层与微隔离 采用零信任架构,将内网划分为核心区、业务区、DMZ区等逻辑区域&a…...
智能电视网页浏览新选择:TV Bro浏览器如何改变你的大屏体验
智能电视网页浏览新选择:TV Bro浏览器如何改变你的大屏体验 【免费下载链接】tv-bro Simple web browser for android optimized to use with TV remote 项目地址: https://gitcode.com/gh_mirrors/tv/tv-bro 你是否曾在智能电视上尝试浏览网页,却…...
IC设计五大典型Bug剖析:从CDC到软硬件协同的防御性设计
1. 项目概述:IC设计中的那些“老朋友”在芯片设计的江湖里混迹多年,我越来越觉得,我们这些IC工程师(ICer)的日常,与其说是在创造,不如说是在与各种层出不穷的“老朋友”——也就是bug——斗智斗…...
5分钟掌握ncmdumpGUI:将网易云ncm文件转换为MP3的完整解决方案
5分钟掌握ncmdumpGUI:将网易云ncm文件转换为MP3的完整解决方案 【免费下载链接】ncmdumpGUI C#版本网易云音乐ncm文件格式转换,Windows图形界面版本 项目地址: https://gitcode.com/gh_mirrors/nc/ncmdumpGUI 你是否曾为网易云音乐下载的ncm文件…...
Treelink选择工具:基于树形结构与链接关系的智能对象筛选方案
1. 项目概述:为什么我们需要“简化模拟选择”?在仿真分析、游戏开发、影视特效乃至工业设计领域,“模拟选择”是一个高频且令人头疼的操作。无论是为3D场景中的一片森林批量设置风力参数,还是在电路仿真中挑选特定节点进行信号分析…...
