RPC--自定义注解注册发布服务

自定义的三个注解

1、RpcReference

这个注解用于修饰类的某个字段,表示这个字段是远程调用的引用

下面详细解释下这个字段的定义

  • @Document表示这个注解应该被javadoc文档工具记录,生成API文档时使用了该注解的地方会被显示出来

  • @Retention表示这个注解的声明周期,它定义了这个注解可以在运行的时候通过反射读取到,也就是可以通过反射来获取到这个注解里的属性

  • @Target表示这个注解只能被加在类的字段上

  • @Inherited表示这个注解具有继承属性,也就是说如果一个类的某个字段有这个注解,那么继承这个类的子类也会继承这个注解的行为

上面那个注解用在client端的调用服务,例如下面的HelloController这个类的HelloService函数,标识这是一个服务的远程调用,框架在启动时通过RpcScan注解自动将远程服务注入为代理对象

然后在运行过程中通过反射拿到代理对象上面的RpcReference注解的属性,获取里面的version和group的值

2、RpcService

这个注解通常用在服务类上, 标注这个类实现了一个远程接口,并希望将其作为实例暴露给远程调用

下面详细解释下这个字段的定义

  • @Document表示这个注解应该被javadoc文档工具记录,生成API文档时使用了该注解的地方会被显示出来

  • @Retention表示这个注解的声明周期,它定义了这个注解可以在运行的时候通过反射读取到,也就是可以通过反射来获取到这个注解里的属性

  • @Target表示这个注解只能被加在类、接口、枚举上面,不能加在某个类或者

  • @Inherited表示这个注解具有继承属性,也就是说如果一个类的某个字段有这个注解,那么继承这个类的子类也会继承这个注解的行为

如下面时他的一个调用实例

3、RpcScan

这个注解用于在Spring框架中启用对RPC服务的自动扫描和注册。通常在一个配置类上,告诉spring哪些包需要被扫描来找到带有RpcReference和RpcService等注解的类,并将其注册为spring bean或者RPC代理对象。

他结合了CustomScannerRegistrar,可以实现:

  • 自动将远程服务接口注入为代理对象(如 @RpcReference)

  • 自动注册本地服务实现为可被调用的 RPC 提供者(如 @RpcService)

下面逐行解析:

@Target里面定义了这个注解可以用在方法、接口和类上面,但实际操作中一般用在配置类上面(加了@Configuration注解用于配置Spring容器的类上面)

@Retention同上面,可以在运行时候通过反射拿到这个注解的属性

@Import注解在配置中引入了CustomScannerRegistrar这个类,这个类是实现自定义扫描包的逻辑的,是一个实现了ImportBeanDefinitionRegistrar接口的类,用来动态注册bean的定义

@Document表示加了这个注解的类会显示在API文档中

里面定义的属性basePackage指定要扫描包的路径

自定义扫描和服务发布的实现

CustomScannerRegistrar实现了spring的ImportBeanDefinitionRegistrar, ResourceLoaderAware接口

重写了RegisterBeanDefinitions方法,spring在启动时会调用这个方法,重写后设置两个自定义扫描器,扫描RpcService注解的类后,扫描Component注解的类保证其他基础组件也能正常加载,扫描到指定类型后注册成spring的bean

其实这里没有对RpcService注解的类做特殊处理,可以自己加?

自定义一个类SpringBeanPostDefinition实现了BeanPostDefinition接口,这个接口用于对spring注册后的bean做后处理。

重新实现这个接口的postProcessBeforeInitialization方法, spring会在每个bean初始化之前调用这个方法,对加了RpcService注解的类生成服务配置进行发布。发布服务就是将该bean的方法信息和netty通信的ip+端口地址拼成一个字符串,在zookeeper中作为一个持久化节点

重写postProcessAfterInitialization这个接口,spring在每个bean初始化之后调用,通过反射获取到这个类的所有字段,遍历这些字段看是不是加了RpcReference字段,如果是的话那么这就是一个远程服务的引用,然后去构建一个服务配置对象保存版本、分组等信息。

然后为这个字段的服务生成一个代理对象,默认情况下这些字段我们都会设置成private,所以要先将这个字段设置成可访问并通过反射将代理对象赋值到这个字段,这样当调用这个字段的方法时,就会通过代理对象远程调用到服务的方法了。

使用代理对象是为了客户端与具体服务解耦,让客户端感觉就像是在调用本地对象的方法一样,不需要知道服务的具体位置、通信协议等细节信息,它只需要知道服务接口以及如何获取代理对象即可。通过动态代理,在客户端创建一个实现了远程服务接口的代理对象。当客户端调用该代理对象的方法时,代理会将方法调用转换为网络请求发送给远程服务器,并处理响应返回给客户端

相关推荐
Bruce_Liuxiaowei1 小时前
常见高危端口风险分析与防护指南
网络·网络安全·端口·信息搜集
tmacfrank1 小时前
Android 网络全栈攻略(四)—— TCPIP 协议族与 HTTPS 协议
android·网络·https
liulilittle1 小时前
深度剖析:OPENPPP2 libtcpip 实现原理与架构设计
开发语言·网络·c++·tcp/ip·智能路由器·tcp·通信
cui_win1 小时前
【内存】Linux 内核优化实战 - net.ipv4.tcp_tw_reuse
linux·网络·tcp/ip
2501_916013742 小时前
iOS 多线程导致接口乱序?抓包还原 + 请求调度优化实战
websocket·网络协议·tcp/ip·http·网络安全·https·udp
M1A12 小时前
TCP/IP协议精解:IP协议——互联网世界的邮政编码系统
后端·网络协议·tcp/ip
夏天想2 小时前
优化 WebSocket 实现单例连接用于打印【待测试 】
网络·websocket·网络协议
路长且阻3 小时前
网络协议(TCP/IP、HTTP、HTTPS)
网络协议·tcp/ip·http
杰尼橙子3 小时前
DPDK基础架构解析:EAL环境抽象层的设计与实现
网络协议·性能优化
我是小bā吖3 小时前
阿里云服务网格ASM实践
网络·阿里云·云计算·服务发现