当前位置: 首页 > news >正文

动态代理:面向接口编程,屏蔽RPC处理过程

RPC远程调用

使用 RPC 时,一般的做法是先找服务提供方要接口,通过 Maven把接口依赖到项目中。在编写业务逻辑的时候,如果要调用提供方的接口,只需要通过依赖注入的方式把接口注入到项目中,然后在代码里面直接调用接口的方法 。

接口里并不会包含真实的业务逻辑,业务逻辑都在服务提供方。

核心技术:动态代理

RPC 会自动给接口生成一个代理类,项目中注入接口的时候,运行过程中实际绑定的是这个接口生成的代理类。在接口方法被调用的时候,实际上是被生成代理类拦截到,这样就可以在生成的代理类里面,加入远程调用逻辑。
流程如下:
image-20241028222602052

实现原理

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 目录里面。

生成的代理类。

image-20241028234309430

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能完成代理功能,还有很多其他的第三方框架也可以实现,比如JavassistByte 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> /********************************************************…...

【常用数据结构】开发中常用的数据结构?

开发中常用的数据结构包括数组、链表、栈、队列、树、图、堆和散列表&#xff08;哈希表&#xff09;‌。这些数据结构在软件开发中有着广泛的应用&#xff0c;并且各自具有独特的特点和用途。 数组 数组是最基本的数据结构之一&#xff0c;用于在内存中连续存储多个元素。数…...

OCC 点云

OCC的基础知识可能还是要系统学习一下&#xff0c;部分导入的模型面类型是很多面都是GeomAbs_BSplineSurface&#xff0c;最终获取参数都要拟合一下&#xff0c;拟合后的生成的面对象没有大小&#xff0c;比如平面只有矢量&#xff08;大小没有思路&#xff09; 圆柱拟合面没有…...

方法重写与方法重载

1. 方法重载与方法重写的定义 方法重写&#xff08;Overriding&#xff09; 方法重写&#xff08;Overriding&#xff09;是指在子类中重新定义与父类中相同的方法。此操作允许子类提供特定的实现&#xff0c;以替代父类的实现。方法重写是实现多态性&#xff08;Polymorphis…...

Vue3实现地球上加载柱体

最终效果为上图。 实现该技术&#xff0c;需要一些技术&#xff0c;我分别罗列一下&#xff1a; canvas&#xff1a;需要使用canvas根据json来绘制地球&#xff0c;不懂的可以看这篇canvas绘制地球 threejs&#xff1a;需要会使用threejs&#xff0c;这里并没有使用shader&am…...

OpenGL入门003——使用Factory设计模式简化渲染流程

前面两节已经学会了如何使用opengl创建窗口并绘制三角形&#xff0c;我们可以看出有些步骤是固定的&#xff0c;而且都写在main.cpp&#xff0c;这一节我们将了解如何使用Factroy设计模型。将模型渲染逻辑封装在一个单独的类中&#xff0c;简化开发流程&#xff0c;且提高代码复…...

01_AI编程案例展示:借助AI轻松爬取海量网盘链接

爬虫案例展示 今天,我们将展示如何利用AI快速开发一个网络爬虫&#xff0c; 使用的工具是Python和Claude 3.5 Sonnet(国内可用豆包替代) 我们的目标是爬取panhub.fun网站上的夸克网盘链接, 即使你是编程新手,也可以轻松完成这样的任务。 案例1-批量爬取panhub网盘整合包 下…...

【机器学习导引】ch5-神经网络

Q&A 1x1 卷积层在深度学习中的作用&#xff1f; 1x1 卷积层在深度学习中具有几个重要的作用&#xff1a; 通道压缩&#xff1a;1x1卷积可以通过调整输出通道数来减少特征图的深度&#xff0c;从而降低计算成本和参数数量。这有助于在保持特征的情况下简化模型。特征融合&am…...

【Axure原型分享】颜色选择器——填充颜色

今天和大家分享颜色选择器——填充颜色的原型模板&#xff0c;点击颜色区域可以弹出颜色选择器&#xff0c;点击可以选择对应颜色&#xff0c;颜色区域会变色我们选择的颜色&#xff0c;具体效果可以观看下方视频或者打开预览地址体验。 【原型效果】 【Axure高保真原型】颜色…...

怎么安装行星减速电机才是正确的

行星减速电机由于其高效、精密的传动能力&#xff0c;广泛应用于自动化设备、机器人、机床以及其他需要精准控制的领域。正确的安装行星减速电机对于确保设备的性能与延长使用寿命至关重要。 一、前期准备 在进行行星减速电机的安装之前&#xff0c;必须做好充分的前期准备工作…...

Qwen2.5-0.5B-Instruct新手入门:从零到一的AI助手搭建全流程

Qwen2.5-0.5B-Instruct新手入门&#xff1a;从零到一的AI助手搭建全流程 1. 认识Qwen2.5-0.5B-Instruct 1.1 模型特点与优势 Qwen2.5-0.5B-Instruct是阿里开源的通义千问系列中最轻量级的指令微调版本&#xff0c;专为资源有限环境优化设计。这个5.08亿参数的模型虽然体积小…...

PyTorch 2.8镜像法律科技:庭审音视频→AI摘要+关键帧提取+证据链可视化

PyTorch 2.8镜像法律科技&#xff1a;庭审音视频→AI摘要关键帧提取证据链可视化 1. 镜像概述与法律科技应用场景 在司法数字化进程中&#xff0c;庭审音视频处理正面临三大挑战&#xff1a;海量数据难以快速消化、关键信息提取效率低下、证据呈现方式单一。PyTorch 2.8深度学…...

一步步教你获取ADNI影像数据:从搜索到下载全流程解析

1. ADNI数据库简介与准备工作 ADNI&#xff08;Alzheimers Disease Neuroimaging Initiative&#xff09;是全球最权威的阿尔茨海默病研究数据库之一&#xff0c;包含了大量脑部影像数据和临床信息。第一次接触这个数据库的研究者可能会被复杂的界面和操作流程吓到&#xff0c;…...

Qwen3-ASR-0.6B作品集:Qwen3-ForcedAligner-0.6B时间戳精度图谱

Qwen3-ASR-0.6B作品集&#xff1a;Qwen3-ForcedAligner-0.6B时间戳精度图谱 你有没有想过&#xff0c;一段语音里的每个字、每个词&#xff0c;甚至每个音节&#xff0c;是在哪个精确的时间点被说出来的&#xff1f;这听起来像是电影后期制作里的黑科技&#xff0c;但现在&…...

【MySQL】第五节 - 事务实战详解:从基础到并发控制(附 Navicat 可运行实验脚本)

《MySQL 事务实战详解&#xff1a;从基础到并发控制&#xff08;附 Navicat 可运行实验脚本&#xff09;》 为什么你必须掌握 MySQL 事务&#xff1f; 在现代应用系统中&#xff0c;数据一致性是核心诉求。事务&#xff08;Transaction&#xff09; 是保证数据完整性的“黄金…...

LAMMPS read_data命令保姆级教程:从MS建模到data文件生成的完整避坑指南

LAMMPS read_data命令全流程实战&#xff1a;从分子建模到多体系合并的进阶指南 当你在Materials Studio中精心构建的分子模型终于完成&#xff0c;准备转入LAMMPS进行分子动力学模拟时&#xff0c;是否曾被data文件的各种格式要求绊住脚步&#xff1f;作为连接建模软件与计算引…...

人脸识别OOD模型在金融领域的身份验证应用

人脸识别OOD模型在金融领域的身份验证应用 1. 引言 想象一下这样的场景&#xff1a;一位银行客户正在通过手机APP进行大额转账&#xff0c;系统需要快速准确地确认他的身份。传统的人脸识别系统可能会因为光线不佳、佩戴口罩或者图像模糊而无法正常工作&#xff0c;甚至可能被…...

Windows Cleaner:开源磁盘清理工具的全方位解决方案

Windows Cleaner&#xff1a;开源磁盘清理工具的全方位解决方案 【免费下载链接】WindowsCleaner Windows Cleaner——专治C盘爆红及各种不服&#xff01; 项目地址: https://gitcode.com/gh_mirrors/wi/WindowsCleaner 在数字工作环境中&#xff0c;磁盘空间不足已成为…...

RSA2 - Writeup by AI

RSA2 - Writeup by AI 题目信息项目内容题目来源Bugku CTF题目类型Crypto (密码学)考点RSA 小指数攻击、Rabin 加密题目描述 给定 RSA 加密参数&#xff1a; 加密指数 e 2模数 N&#xff08;3072 位&#xff09;密文 c 要求解密得到 flag。 考点分析 核心知识点 RSA 小指数攻击…...

轻量级跨平台桌面应用开发:Tauri零门槛实战指南

轻量级跨平台桌面应用开发&#xff1a;Tauri零门槛实战指南 【免费下载链接】tauri Build smaller, faster, and more secure desktop and mobile applications with a web frontend. 项目地址: https://gitcode.com/GitHub_Trending/ta/tauri 在桌面应用开发领域&#…...