Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >dubbo SPI 主要配置技术解读

dubbo SPI 主要配置技术解读

原创
作者头像
技术蓝海
修改于 2020-10-26 04:06:34
修改于 2020-10-26 04:06:34
93010
代码可运行
举报
文章被收录于专栏:wannshan(javaer,RPC)wannshan(javaer,RPC)
运行总次数:0
代码可运行

所谓SPI就是接口由框架定义,具体实现可以有不同供应商提供不同的实现。

dubbo在JDK基础上对SPI做了改进和扩展。

dubbo 的SPI 不但实现了实现类的动态加载,还实现了类似spring 的IOC,AOP的功能

本文就上述功能讲下具体使用方法

基本SPI 配置

dubbo 源码包的有些模块的 META-INF/dubbo/目录下 有以接口名命名的文件,里面有是 name=类全面形式的内容

比如

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
META-INF/dubbo/org.apache.dubbo.rpc.Protocol 文件的内容有
dubbo=org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol

DubboProtocol的实现类是dubbo默认的调用协议实现

这样就可以在我们使用dubbo的配置文件中,通过 name 指定我们用的Protocol具体哪个实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<dubbo:protocol name="dubbo"/>

同样你可以添加自己的实现类,比如x.y.z.XXXProtocol 让后在META-INF/dubbo/org.apache.dubbo.rpc.Protocol 文件中添加 新的一行 xxx=x.y.z.XXXProtocol 然后就可以在配置中使用了,这就是最基本的SPI功能。

IOC功能

dubbo不只是还实现了依赖注入的功能,比如DubboProtocol 先类种有个属性filter

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class DubboProtocol extends AbstractProtocol {
    public Filter filter;
    public void setFilter(Filter filter) {
        this.filter = filter;
    }
...
}

Filter 本身也一个接口,可以是@SPI接口,也可以是spring的一个bean

dubbo也可以自动从dubbo 扩展或者spring容器中找到实现类型自动注入

有个问题,如果dubbo org.apache.dubbo.rpc.Filter的文件中有多个实现配置,比如

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
mockfilter=org.apache.dubbo.config.mock.MockFilte
orc=org.apache.dubbo.config.orc.OrcFilte
mov=org.apache.dubbo.config.mov.MovFilter

应该用哪一个类呢?这就要用到Adaptive注解,比如

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Adaptive
public class MockFilter implements Filter {}

这个就表示用 MockFilter类作为实现类

关于@Adaptive注解,它还能写在接口方法上,如果不在类上指定dubbo 会为这个接口自动生成一个 接口名$Adpative 命名的实现类。比如 dubbo Protocol接口 refer方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@SPI("dubbo")
public interface Protocol {
    @Adaptive //没在类中指定,写在了方法上
    <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;
.....
}

dubbo 动态生成的Adapatvie类和refer方法实现如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Protocol$Adpative implements com.alibaba.dubbo.rpc.Protocol {
   .....
    public com.alibaba.dubbo.rpc.Invoker refer(java.lang.Class arg0, com.alibaba.dubbo.common.URL arg1) throws com.alibaba.dubbo.rpc.RpcException {
        if (arg1 == null) throw new IllegalArgumentException("url == null");
        com.alibaba.dubbo.common.URL url = arg1;
        String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
        if (extName == null)
            throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");
        com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);
        return extension.refer(arg0, arg1);
    }
......
}

可以看到,它实现的功能就是通过调用时url中的参数指定具体哪个实现类。

AOP

AOP就动态方法包装,完成切面编程,dubbo是通过 wrapper类实现的。

还是文件org.apache.dubbo.rpc.Protocol 文件,里面有这些配置

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
filter=org.apache.dubbo.rpc.protocol.ProtocolFilterWrappe
listener=org.apache.dubbo.rpc.protocol.ProtocolListenerWrappe
mock=org.apache.dubbo.rpc.support.MockProtocol

其中 ProtocolFilterWrapper就是Wrapper类,并不是因为类名有Wrapper,而是由于实现中有Protocol 接口类型的构造函数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Activate(order = 100)
public class ProtocolFilterWrapper implements Protocol {
    private final Protocol protocol;
    public ProtocolFilterWrapper(Protocol protocol) {
        if (protocol == null) {
            throw new IllegalArgumentException("protocol == null");
        }
        this.protocol = protocol;
    }
...
   //对refer实现了包装
    @Override
    public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
        if (UrlUtils.isRegistry(url)) {
            return protocol.refer(type, url);
        }
        return buildInvokerChain(protocol.refer(type, url), REFERENCE_FILTER_KEY, CommonConstants.CONSUMER);
    }
}
//另外一个Wrappe
@Activate(order = 200)
public class ProtocolListenerWrapper implements Protocol {
    private final Protocol protocol;
    public ProtocolListenerWrapper(Protocol protocol) {
        if (protocol == null) {
            throw new IllegalArgumentException("protocol == null");
        }
        this.protocol = protocol;
    }
...
}

想必你注意到了@Activate(order = 200)注解,它指定多个wrapper 的排序,通过@Activate的order属性排序。

Activate

比如常用的Filter, InvokerListener, ExportListener, TelnetHandler, StatusChecker 等实现集合,我们可以通过 Activate注解完成多个实现类的一次加载和激活,还能配置条件激活,比如

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Activate // 任何条件下激活
public class XxxFilter implements Filter {
    // ...
}
@Activate(group = "provider", value = "cache") //这个就是在group是“provider”  value 等于cache 下激活
public class CacheFilter  implements Filter {
    // ...
}

这个功能的实现可看 ExtensionLoader类的getActivateExtension方法:

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
1 条评论
热度
最新
dubbo 基础
dubbo 基础
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
Dubbo 是如何实现 SPI 机制?
SPI 全称是 Service Provider Interface,是一种服务发现机制。
FoamValue
2020/10/23
8000
dubbo SPI机制源码分析
dubbo是微内核架构,SPI是dubbo的架构根基 什么是微内核?还是开闭原则的应用。把核心流程架构固定,但流程各个节点对重新改进是开放的,也可以说是面下接口编程。具体实现方法就是SPI(servi
技术蓝海
2018/04/26
1.7K0
【DUBBO】 扩展机制ServiceLoaderExtensionLoader
可扩展机制也就是SPI(Service Provider Interface)了,SPI是一种服务提供发现机制。一个服务通常指的是已知的接口,服务提供方就是这个接口的实现类,然后按照SPI标准存放到资源路径META-INF/services目录下,文件的命名为该服务接口的全限定名。
spilledyear
2018/12/21
9760
dubbo源码学习之SPI(二)
在Dubbo中,SPI是一个非常核心的机制,贯穿在几乎所有的流程中。搞懂这块内容,是接下来了解Dubbo更多源码的关键因素。
周杰伦本人
2022/10/25
3320
dubbo源码学习之SPI(二)
Dubbo服务提供者发布过程
首先ServiceConfig类拿到对外提供服务的实际类ref(如:HelloServiceImpl),然后通过ProxyFactory类的getInvoker方法使用ref生成一个AbstractProxyInvoker实例,到这一步就完成具体服务到Invoker的转化。接下来就是Invoker转换到Exporter的过程。
搜云库技术团队
2019/10/18
5130
【Dubbo源码】SPI机制源码解析
SPI 全称为 Service Provider Interface,是一种服务发现机制。SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。这样可以在运行时,动态为接口替换实现类。正因此特性,我们可以很容易的通过 SPI 机制为我们的程序提供拓展功能。SPI 机制在第三方框架中也有所应用,比如 Dubbo 就是通过 SPI 机制加载所有的组件。不过,Dubbo 并未使用 Java 原生的 SPI 机制,而是对其进行了增强,使其能够更好的满足需求。在 Dubbo 中,SPI 是一个非常重要的模块。基于 SPI,我们可以很容易的对 Dubbo 进行拓展。如果大家想要学习 Dubbo 的源码,SPI 机制务必弄懂。接下来,我们先来了解一下 Java SPI 与 Dubbo SPI 的用法,然后再来分析 Dubbo SPI 的源码。
石臻臻的杂货铺[同名公众号]
2021/07/14
1.5K0
[转] 理解 Dubbo SPI 扩展机制
    最近接触了 gRPC 体会到虽然众多 RPC 框架各有各的特点但是他们提供的特性和功能有很多的相似之处 , 这就说明他们面对同样的分布式系统带来的问题。从 2016 年左右开始接触到 dubbo ,基本停留在使用的层面,对 dubbo 的设计以及着重要解决的问题都没有系统的研究过,通过对 dubbo 和其他类似 RPC 产品的系统学习 ,学习分布式系统中面临的共同问题以及解决之道。 
JMCui
2019/06/03
4730
Dubbo SPI实现原理
Dubbo 并未使用 Java 原生的 SPI 机制,而是对其进行了增强,使其能够更好的满足需求,在 Dubbo 中,SPI 是一个非常重要的模块。基于 SPI,我们可以很容易的对 Dubbo 进行拓展. 本篇文章通过示例说明,先 download 代码,然后在 demo-dubbo--》dubbo-demo-api--》dubbo-demo-api-provider 下新建类:
LiosWong
2019/11/06
1.3K0
Dubbo SPI实现原理
二、SPI 自适应拓展
本文是自己阅读dubbo源码的时候的见解,因为sb微信觉得我跟另一个人的重复率太高(他是纯copy官方文档),所以不能搞原创,,自闭gg,要不是公众号自己复习方便,真的是不用了。。。
JathonKatu
2022/12/02
2200
dubbo源码之SPI AdaptiveExtension和Wrapper
在之前的推文中我们知道,dubbo有很多SPI的拓展点,而ExtensionLoader又是dubbo SPI拓展点的加载器。这篇文章中我们将以ExtensionLoader为切入点来对dubbo的SPI机制进行分析。dubbo中的SPI拓展点的主要位置在:
山行AI
2019/07/16
1K0
dubbo源码之SPI AdaptiveExtension和Wrapper
Java必备之从JDK到Dubbo的SPI深度剖析
本示例路径META-INF/services/com.springboot.dubbo.spi.SayHelloService
用户5397975
2019/10/14
9660
二(拓展)@Adaptive
在实际应用场景中,一个扩展接口往往会有多种实现类,因为Dubbo是基于URL驱动,所以在运行时,通过传入URL中的某些参数来动态控制具体实现,这便是Dubbo的扩展点自适应特性。
JathonKatu
2022/12/02
3400
Dubbo——SPI及自适应扩展原理
Dubbo虽然已交由apache管理,并且社区活跃度也不如SpringCloud,但也是国内应用比较广泛的RPC框架,其背后的设计思想非常值得我们学习借鉴。鉴于Dubbo官方文档对于基础的使用配置已经讲解的非常清楚了,这里就不再赘述。本系列文章将基于Dubbo2.5.3版本的源码做分析。而Dubbo中最核心的一点就是SPI和自适应扩展,Dubbo的高扩展性以及其它功能都是在这个基础上实现的,理解掌握其原理才能看懂后面的一系列功能的实现原理,对我们平时实现高扩展性也非常有帮助。(PS:Dubbo源码不像Zookeeper那样有明确的入口,可以根据官网的源码分析指导找到。)
夜勿语
2020/09/07
6120
Dubbo spi机制_dubbo负载均衡
dubbo中提供了一个ExtensionLoader.getLoadingStrategies()方法,但是在dubbo3.0.6版本已经废弃,取而代之的是几个区分了模块的类,ApplicationModel、FrameworkModel、ModuleModel
全栈程序员站长
2022/11/15
5740
Dubbo spi机制_dubbo负载均衡
Dubbo系列一之Provider启动
通过@EnableDubbo注解启动,该注解整合了@EnableDubboConfig和@DubboCompoentScan,这两个注解分别import了DubboConfigConfigurationRegistrar和DubboComponentScanRegistrar
用户9511949
2024/07/15
1320
dubbo消费方服务调用过程源码分析
dubbo PRC服务调用过程很复杂,这里准备通过分析一个典型rpc方法调用的调用栈来说明调用过程。说它典型,是因为本次分析的调用场景很典型简单 先定义一个接口 public interface DemoService { public String sayHello(String name); } 然后一个服务实现类 public class DemoServiceImpl implements DemoService { public String sayHello(S
技术蓝海
2018/04/26
5.5K4
Dubbo剖析-增强SPI中扩展点自动包装的实现
在Spring AOP中可以使用多个切面对指定类的方法进行增强,在Dubbo中也提供了类似的功能,在dubbo中你可以指定多个Wrapper类对指定的扩展点的实现类的方法进行增强。
加多
2018/09/06
8240
dubbo 的 spi 思想
spi,简单来说,就是 service provider interface,说白了是什么意思呢,比如你有个接口,现在这个接口有 3 个实现类,那么在系统运行的时候对这个接口到底选择哪个实现类呢?这就需要 spi 了,需要根据指定的配置或者是默认的配置,去找到对应的实现类加载进来,然后用这个实现类的实例对象。
IT技术小咖
2019/06/26
6160
dubbo 的 spi 思想
dubbo源码学习之服务发布调用链 消费者消费调用链(三)我太难了。。
dubbo 是基于 spring 配置来实现服务的发布的,那么一定是基于 spring的扩展来写了一套自己的标签,那么 spring 是如何解析这些配置呢?总的来说,就是可以通过 spring 的扩展机制来扩展自己的标签。大家在dubbo 配置文件中看到的dubbo:service ,就是属于自定义扩展标签
周杰伦本人
2022/10/25
4500
dubbo源码学习之服务发布调用链 消费者消费调用链(三)我太难了。。
dubbo 源码 v2.7 分析:核心机制(一)
上一篇我们介绍了SPI机制。本篇会先介绍dubbo中的核心机制,包括设计模式、bean加载、扩展点机制、动态代理和远程调用流程。
程序员架构进阶
2021/03/04
6580
dubbo 源码 v2.7 分析:核心机制(一)
相关推荐
Dubbo 是如何实现 SPI 机制?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档