关于dubbo扩展点的一点分析
扩展点能力
- 能load class,这个class除了顶层接口class(在ExtensionLoader中对应type字段),还能load各实现类的class。
- 能创建instance。
- 能指定这个顶层接口的默认实现类的beanName。做法参见SPI注解部分。
- 能把创建出来的instance的字段注入。set开头的且有一个参数且是public的,注入。
- 能adaptive。根据url上对该接口配置的实现类,将该接口的事情交给这个实现类去做(我更多的理解成委托)。此能力采用代码生成再编译的方式。代码生成示例可以参见adaptive类代码示例。 adaptive只会生成一个adaptive实现类。生成代码的逻辑在com.alibaba.dubbo.common.extension.ExtensionLoader.createAdaptiveExtensionClassCode()
- 能wrapper。wrapper是指这个顶层接口的实现类的构造函数的入参是这个顶层接口类型。那么这个实现类称之为wrapper类,可以有多个,构建instance时不分多个之间的顺序。因为用来给构造函数传参的instance是这个顶层类的默认实现。比如com.alibaba.dubbo.rpc.Protocol接口,有实现类 com.alibaba.dubbo.rpc.protocol.injvm.InjvmProtocol beanName是injvm,QosProtocolWrapper、ProtocolListenerWrapper、ProtocolFilterWrapper是其三个wrapper类。创建warpper instance的代码逻辑在com.alibaba.dubbo.common.extension.ExtensionLoader.createExtension(String)中。
- 能active。实现类加了Activate注解的。在ExtensionLoader.getActivateExtension时会根据当前的url(配置信息)中值来匹配Activate注解中指定的值是否能match,能match的表示是activate,意思是命中的。在过滤器扩展点中用到。比如这个过滤器是给CONSUMER group用。示例有ExceptionFilter等。同时该注解还能支持order属性来定义bean的顺序。
扩展点使用
配置文件相关
配置文件放在哪里?
- META-INF/dubbo/internal/配置文件
- META-INF/dubbo/配置文件
- META-INF/services/配置文件
配置文件名是顶层接口全限定名,比如:com.alibaba.dubbo.rpc.Protocol
配置文件中内容:
一行是一个实现类的定义,大致是
beanName=实现类的class的全限定名,这个后面还可以接上#xxx(这个能力实际使用少)。beanName=这部分不是必须的。可以仅仅写实现类的全限定名。
注解相关
SPI
SPI注解用在顶层接口上,其值表示这个接口的默认实现类的beanName,也即是说指定一个顶层接口的默认实现通过SPI注解加载顶层接口上指定即可。
Adaptive
Adaptive注解用在顶层接口或者接口的方法上,其表示这个接口或者这个方法需要有adaptive的类委托完成,未加注解的会生成不支持的操作的方式实现。
Activate
Activate注解用在实现类上,其表示实现类在rpc时根据url参数中以及注解中指定的key 目标value是否能匹配来决定此bean是否被选中(一般用在过滤器的命中判断上)。
生成的代码
adaptive类代码示例
package com.alibaba.dubbo.registry;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
public class RegistryFactory$Adaptive implements com.alibaba.dubbo.registry.RegistryFactory {
public com.alibaba.dubbo.registry.Registry getRegistry(com.alibaba.dubbo.common.URL arg0) {
if (arg0 == null)
throw new IllegalArgumentException("url == null");
com.alibaba.dubbo.common.URL url = arg0;
String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
if (extName == null)
throw new IllegalStateException(
"Fail to get extension(com.alibaba.dubbo.registry.RegistryFactory) name from url(" + url.toString()
+ ") use keys([protocol])");
com.alibaba.dubbo.registry.RegistryFactory extension = (com.alibaba.dubbo.registry.RegistryFactory) ExtensionLoader
.getExtensionLoader(com.alibaba.dubbo.registry.RegistryFactory.class).getExtension(extName);
return extension.getRegistry(arg0);
}
}
package com.alibaba.dubbo.rpc.cluster;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
public class Cluster$Adaptive implements com.alibaba.dubbo.rpc.cluster.Cluster {
public com.alibaba.dubbo.rpc.Invoker join(com.alibaba.dubbo.rpc.cluster.Directory arg0)
throws com.alibaba.dubbo.rpc.RpcException {
if (arg0 == null)
throw new IllegalArgumentException("com.alibaba.dubbo.rpc.cluster.Directory argument == null");
if (arg0.getUrl() == null)
throw new IllegalArgumentException("com.alibaba.dubbo.rpc.cluster.Directory argument getUrl() == null");
com.alibaba.dubbo.common.URL url = arg0.getUrl();
String extName = url.getParameter("cluster", "failover");
if (extName == null)
throw new IllegalStateException(
"Fail to get extension(com.alibaba.dubbo.rpc.cluster.Cluster) name from url(" + url.toString()
+ ") use keys([cluster])");
com.alibaba.dubbo.rpc.cluster.Cluster extension = (com.alibaba.dubbo.rpc.cluster.Cluster) ExtensionLoader
.getExtensionLoader(com.alibaba.dubbo.rpc.cluster.Cluster.class).getExtension(extName);
return extension.join(arg0);
}
}
杂项
查找所有的dubbo扩展点形式的配置文件
find ./ -type f -name "com.alibaba.dubbo*"|grep -v "/target/"|grep -v "/bin/"|grep -v "/test/"
另:
关于代理模式,dubbo未实现通用的,只是rpc语义实现里rpc调用的代理,借助扩展点机器加动态代理完成。
具体其顶层接口是com.alibaba.dubbo.rpc.ProxyFactory。用在比如将EchoService编织进每次RPC调用中。
关于dubbo扩展点的一点分析的更多相关文章
- Dubbo系列讲解之扩展点实现原理分析【2万字分享】
Apache Dubbo 是一款微服务开发框架,它提供了 RPC通信 与 微服务治理 两大关键能力.这意味着,使用 Dubbo 开发的微服务,将具备相互之间的远程发现与通信能力, 同时利用 Dubbo ...
- 从Spring容器的角度理解Dubbo扩展点的加载时机
对于Dubbo提供的扩展点,主程序执行的过程中并没有显示调用加载的过程,无论是自激活的Filter还是自适应的ThreadPool.那么这样的扩展点在程序运行的哪个节点调用的呢?跟踪之前性能监控扩展点 ...
- App store 应用审核由于 IPv6 网络问题被拒的一点分析
App store 应用审核由于 IPv6 网络问题被拒的一点分析 六月以后陆续有一些软件提交市场的时候被拒了,症状基本就是无法登陆啥的.我们公司的应用也未能幸免. 很多同学也想了不少办法,申诉. ...
- Linq分组操作之GroupBy,GroupJoin扩展方法源码分析
Linq分组操作之GroupBy,GroupJoin扩展方法源码分析 一. GroupBy 解释: 根据指定的键选择器函数对序列中的元素进行分组,并且从每个组及其键中创建结果值. 查询表达式: var ...
- Dubbo扩展点应用之二负载均衡
负载均衡其本质就是将请求分摊到多个操作单元上进行,从而共同完成工作任务.其策略主要用于客户端春常在多个提供者时根据算法选择某个提供者.在集群负载均衡时,Dubbo提供了多种均衡策略(包括随机.轮询.最 ...
- Dubbo 扩展点加载机制:从 Java SPI 到 Dubbo SPI
SPI 全称为 Service Provider Interface,是一种服务发现机制.当程序运行调用接口时,会根据配置文件或默认规则信息加载对应的实现类.所以在程序中并没有直接指定使用接口的哪个实 ...
- Dubbo SPI 机制源码分析(基于2.7.7)
Dubbo SPI 机制涉及到 @SPI.@Adaptive.@Activate 三个注解,ExtensionLoader 作为 Dubbo SPI 机制的核心负责加载和管理扩展点及其实现.本文以 E ...
- Dubbo的优雅下线原理分析
文/朱季谦 Dubbo如何实现优雅下线? 这个问题困扰了我一阵,既然有优雅下线这种说法,那么,是否有非优雅下线的说法呢? 这,还真有. 可以从linux进程关闭说起,其实,我们经常使用到杀进程的指令背 ...
- 2048游戏分析、讨论与扩展 - Part I - 游戏分析与讨论
2048这个游戏从刚出開始就风靡整个世界. 本技术博客的目的是想对2048涉及到相关的全部问题进行仔细的分析与讨论,得到一些大家能够接受而且理解的结果. 在这基础上,扩展2048的游戏性,使其变得更好 ...
随机推荐
- css选择器大全
1.元素选择器 这是最基本的CSS选择器,HTML文档中的元素本身就是一个选择器: p {line-height:1.5em; margin-bottom:1em;} //设置p元素行高1.5em,距 ...
- 【mysql】- 索引简介篇
简介 我们都知道mysql使用存储引擎的是InnoDB,InnoDB使用的索引的对应的数据结构是B+树 结构图: 如上图所示,我们实际用户记录是存放在B+树的最底层的节点上,这些节点也被称为叶子节点或 ...
- Nginx配置多个域名指向不同的端口
一.前言 很多时候我们都会在同一个服务器上部署多个项目,我们有多个域名的情况下,怎么样使不同的域名都通过80端口来访问呢?打个比方说,现在有2个域名,分别是:tessai.cn 和 admin.tes ...
- SQL查询基本用法
-- 单列查询 select 编号 from employees -- 多列查询 select 编号,姓名 from employees -- 查询所有列 select * from employee ...
- python socket函数详解
关于socket函数,每个的意义和基本功能都知道,但每次使用都会去百度,参数到底是什么,返回值代表什么意义,就是说用的少,也记得不够精确.每次都查半天,经常烦恼于此.索性都弄得清楚.通透,并记录下来, ...
- shell 输出json格式的内容
对于shell脚本的输出,如果要输出json格式的内容,我们可以借助python -m json.tool命令 比如 echo '{"name":"zhangsan&qu ...
- vue -电子时钟
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- C#winform将dll封装到exe当中
我们在在winform程序时经常会用到外部dll,正常情况下,我的exe运行文件旁就需要这些dll文件相伴,总感觉不爽~~特别是要把软件给别人的时候,如果DLL比较多或者没有放在同一个地方,那麻烦大了 ...
- Django开发之ORM批量操作
版本 1 Python 3.8.2 2 Django 3.0.6 批量入库 场景: 前端页面通过 textarea 文本框提交一列多行数据到Django后台,后台通过ORM做入库操作 表名: Tabl ...
- 第四章 常用API(上)
4.1.Object类 描述:该类是所有类的最终根类 方法 描述 public boolean equals(Object obj) 表示某个其它对象是否"等于"此对象 publi ...