RPC使用JDK动态代理

介绍

在 Java 动态代理机制中 InvocationHandler 接口和 Proxy 类是核心。
Proxy类中使用频率最高的方法是:newProxyInstance() ,这个方法主要用来生成一个代理对象。

public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)throws IllegalArgumentException{.....
}

这个方法一共有 3 个参数:
1.loader :类加载器,用于加载代理对象。
2.interfaces:被代理类实现的一些接口。
3.h:实现了 InvocationHandler 接口的对象。


要实现动态代理的话,还必须实现 InvocationHandler 来自定义处理逻辑。当我们的动态代理对象调用一个方法时候,这个方法的调用就会被转发到实现 InvocationHandler 接口类的 invoke 方法来调用。
 

JDK动态代理类使用步骤

1.定义一个接口及其实现类。
2.自定义 InvocationHandler 并重写 invoke 方法,在 invoke 方法中我们会调用原生方法(被代理类的方法) 并自定义一些处理逻辑。
3 .通过 Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h) 方法创建代理对象。
 

代码示例

1.定义发送短信的接口

public interface SmsService {String send(string message);
}

2.实现发送短信的接口

public class SmsServiceImpl implements SmsService {public String send(String message) {System.out.println("send message:"+ message);return message;}
}

3.定义一个JDK动态代理类

public class DebugInvocationHandler implements InvocationHandler {//代理类中的真实对象private final Object target;public DebugInvocationHandler(Object target) {this.target = target;}public 0bject invoke(Object proxy, Method method, 0bject[] args) throws InvocationTargetException, IllegalAccessException{//调用方法之前,我们可以添加自己的操作System.out.println("before method " + method.getName());Obiect result = method.invoke(target, args);//调用方法之后,我们同样可以添加自己的操作System.out.println("after method " + method.getName());return result;}
}

invoke() 方法: 当我们的动态代理对象调用原生方法的时候,最终实际上调用到的是 invoke()方法,然后 invoke() 方法代替我们去调用了被代理对象的原生方法。

4.获取代理对象的工厂类

public class JdkProxyFactory{public static Object getProxy(Object target) {return Proxy.newProxyInstance(//目标类的类加载target.getclass().getclassLoader();//代理需要实现的接口,可指定多个target.getClass().getInterfaces()//代理对象对应的自定义InvocationHandlernew DebugInvocationHandler(target));}
}

5.实际使用

SmsService smsService = (SmsService) JdkProxyFactory.getProxy(new SmsServiceImpl());
smsService.send("java")

在RPC中的使用

RpcClientProxy相当于代理对象的工厂类,同时它还实现了InvocationHandler接口,所以它自己也是JDK动态代理类。

这里的getProxy对应工厂类的getProxy方法。

public <T> T getProxy(Class<T> clazz) {// this代表this.invokereturn (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class<?>[]{clazz}, this);
}

第一个<T>表示该方法是泛型方法,第二个T是返回值类型,Class<T> clazz是一个类型为<T>的类。this就代表了它自己,因为自己实现了InvocationHandler接口。

这里的invoke对应动态代理类的invoke方法。

   public Object invoke(Object proxy, Method method, Object[] args) {log.info("invoked method: [{}]", method.getName());// 根据被调用的方法、方法参数等信息构建一个 RpcRequest 对象,表示一个远程过程调用请求RpcRequest rpcRequest = RpcRequest.builder().methodName(method.getName()).parameters(args).interfaceName(method.getDeclaringClass().getName()).paramTypes(method.getParameterTypes()).requestId(UUID.randomUUID().toString()).group(rpcServiceConfig.getGroup()).version(rpcServiceConfig.getVersion()).build();RpcResponse<Object> rpcResponse = null;// 判断rpcResponse的类型if (rpcRequestTransport instanceof NettyRpcClient) {//这里的rpcRequestTransport.sendRpcRequest对应了NettyRpcClient的sendRpcRequestCompletableFuture<RpcResponse<Object>> completableFuture = (CompletableFuture<RpcResponse<Object>>) rpcRequestTransport.sendRpcRequest(rpcRequest);rpcResponse = completableFuture.get();}if (rpcRequestTransport instanceof SocketRpcClient) {rpcResponse = (RpcResponse<Object>) rpcRequestTransport.sendRpcRequest(rpcRequest);}this.check(rpcResponse, rpcRequest);return rpcResponse.getData();

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/200363.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql中year函数有什么用

YEAR()函数用于提取日期或日期时间值中的年份。可以用于提取DATE、DATETIME或TIMESTAMP列中的年份。 SELECT YEAR(date_column) FROM table;# 提取字符串中的数据SELECT YEAR(2023-07-19) FROM table_name;

华容道问题求解第一部分_思路即方案设计

一、前言 华容道是一种传统的益智游戏&#xff0c;通常由一个长方形木板和若干个方块组成。其中包括一个或多个不同颜色的方块&#xff08;也称为车块&#xff09;和其他大小相同的方块&#xff08;也称为障碍块&#xff09;。游戏的目标是将车块从木板的一个端点移动到另一个…

Android 项目的依赖方式

四种依赖方式 在 Android 项目中&#xff0c;有多种方式可以添加项目依赖。以下是几种常见的方式&#xff1a; Gradle 依赖&#xff1a;这是最常用和推荐的方式。在项目的 build.gradle 文件中&#xff0c;你可以使用 dependencies 块来添加依赖项。Gradle 会自动从远程仓库下…

juniper EX系列交换机VLAN配置操作

配置VLAN 初始化配置时候&#xff0c;所有端口属于default VLAN&#xff0c;default vlan的默认ID是0 userhost# set interfaces name unit 0 family ethernet-switching port-mode access #配置端口的access模式&#xff0c;默认端口就是access模式。 userhost#set vlans vl…

销售工作中如何满足客户的需求?

销售工作中如何满足客户的需求&#xff1f; 在销售工作中&#xff0c;如果想要满足客户需求&#xff0c;第一步是要搞清楚客户的需求是什么&#xff0c;不能仅仅听客户的表面需求&#xff0c;在表面需求下隐藏的潜在需求是什么&#xff0c;另外还有客户的核心需求是什么&#…

举个栗子!Alteryx 技巧(8):运用批处理宏,巧妙实现分析流程重复使用

分析用户在 Alteryx Designer 做了一个比较复杂的逻辑处理&#xff0c;因为它的使用频率比较高&#xff0c;如果可以复用就能事半功倍。那么&#xff0c;如何实现多次快速使用呢&#xff1f;方法很简单&#xff1a;运用批处理宏&#xff0c;巧妙实现分析流程重复使用&#xff0…

【Tomcat】java.net.BindException “Address already in use: NET_Bind“

问题 17:37 Error running Tomcat 7.0.76: Unable to open debugger port (127.0.0.1:14255): java.net.BindException "Address already in use: NET_Bind"调整 把14255 改成 49963就正常了 附件 netstat -aon|findstr "49963" taskkill -f -pid xxx…

Linux入门笔记

1 Linux概述 Linux 是一套免费使用和自由传播的类 Unix 操作系统&#xff0c;是一个基于 POSIX 和 UNIX 的多用户、多任务、支持多线程和多 CPU 的操作系统。Linux 能运行主要的 UNIX 工具软件、应用程序和网络协议。它支持 32 位和 64 位硬件。Linux 继承了 Unix 以网络为核心…

【网络奇缘】- 如何自己动手做一个五类|以太网|RJ45|网络电缆

​ ​ &#x1f308;个人主页: Aileen_0v0&#x1f525;系列专栏: 一见倾心,再见倾城 --- 计算机网络~&#x1f4ab;个人格言:"没有罗马,那就自己创造罗马~" 本篇文章关于计算机网络的动手小实验---如何自己动手做一个网线&#xff0c; 也是为后面的物理层学习进…

旋转设备状态监测与预测性维护:提高设备可靠性的关键

在工业领域的各个行业中&#xff0c;旋转设备都扮演着重要的角色。为了确保设备的可靠运行和预防潜在的故障&#xff0c;旋转设备状态监测及预测性维护变得至关重要。本文将介绍一些常见的旋转设备状态监测方法&#xff0c;并探讨如何利用这些方法来实施预测性维护&#xff0c;…

我最喜欢的白版应用,AI加持的新功能开源!强烈推荐

Excalidraw 把他们的文本到图表的功能开源了 Excalidraw是一个虚拟白板应用&#xff0c;专门用于绘制类似手绘的图表。它提供了一个无限的、基于画布的白板&#xff0c;具有手绘风格&#xff0c;支持多种功能。 之前我分享的&#xff1a;72张PNG&#xff0c;图解机器学习 里面…

【Java GUI 开发实践】基于ChannelSftp对Linux虚拟机进行远程指令操作

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 例如:第一章 Python 机器学习入门之pandas的使用 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 系列文章目录前言一、pandas是什么?二、使用步骤1.引入库2.读…

数电笔记之寄存器

数电 1 数字电路基础 1.2 二进制数据表达 1.2.1 二进制简介 1.2.2 用二进制表达文字 常用的中文字符集&#xff1a;GBK&#xff0c;UTF8 1.2.3 用二进制表达图片 图片像素化&#xff0c;像素数字化 1.2.4 用二进制表达声音 1.2.5 用二进制表达视频 1.3 数字电路 1.3…

嵌入式系统学习小结

Microcontroller和Microprocessor啥区别&#xff1f; Microcontroller就是我们说的微控制器&#xff0c;或者说单片机&#xff0c;通常包括CPU和其它parts&#xff0c;包括程序存储器(只读存储器或者闪存), 数据存储器(随机存储器), IO, Clock等在一起。CPU通常计算能力没那么强…

10折交叉验证(10-fold Cross Validation)与留一法(Leave-One-Out)

概念&#xff1a; 交叉验证法&#xff0c;就是把一个大的数据集分为 k个小数据集&#xff0c;其中 k − 1 个作为训练集&#xff0c;剩下的 1 个作为测试集&#xff0c;在训练和测试的时候依次选择训练集和它对应的测试集。这种方法也被叫做 k 折交叉验证法&#xff08;k-fold…

harmony开发之image组件的使用

HarmonyOS是一款面向万物互联时代的、全新的分布式操作系统。 在传统的单设备系统能力基础上&#xff0c;HarmonyOS提出了基于同一套系统能力、适配多种终端形态的分布式理念&#xff0c;能够支持手机、平板、智能穿戴、智慧屏、车机、PC、智能音箱、耳机、AR/VR眼镜等多种终端…

决策树 ID3 算法

ID3 算法 ID3 算法 ID3 算法最早是由罗斯昆 (J.Ross Quinlan) 于1975年提出的一种决策树构建算法&#xff0c;算法的核心是“信息熵”&#xff0c;期望信息越小&#xff0c;信息熵越大&#xff0c;样本纯度越低。。ID3 算法是以信息论为基础&#xff0c;以信息增益为衡量标准…

一位半加法器,一位全加器,四位全加器

我们这里的加法器只考虑一位的情况。 当我们两个一位相加的话&#xff0c;那么就有两个输入&#xff0c;两个输出&#xff0c;两个输入很好理解&#xff0c;就是两个个位上的数字&#xff0c;0或者是1&#xff0c;那么为什么需要有有个输出呢&#xff1f;难道不是输出一个数就…

【3】PyQt文本和图片

1. 文本控件 文本控件是QLabel from PyQt5.QtWidgets import QWidget, QApplication, QLabel import sys# 1.创建应用程序 app QApplication(sys.argv)# 2.创建窗口 w QWidget()# 修改窗口标题 w.setWindowTitle(文本展示)# ---------------------------------------------…

【Trino权威指南(第二版)】Trino介绍:trino解决大数带来的问题

文章目录 一. 大数据带来的问题二. Trino来救场1. 为性能和规模而生2. SQL-on-Anything3. 数据存储与查询计算资源分离 三. Trino使用场景 一. 大数据带来的问题 数据现状 数据存储机制日益多样&#xff1a;关系型数据库、NoSQL数据库、文档数据库、键值存储和对象存储系统等。…