Dubbo的SPI自适应扩展

最近看Dubbo源码的时候,最开始对Dubbo的自适应扩展一直没怎么看明白,参考其他的博客大多也就是把官方的代码解释搬过来,然并卵。

对SPI不明白可以参考官方文档

最后按照自己的理解来模拟了一下,希望对大家能有所帮助。

先定义接口类 SpiTest,有一个mySpi方法:

@SPI //标记为扩展接口public interface SpiTest{

void mySpi(URL url, String name);

}

有两个实现类S1和S2:

public class S1 implements SpiTest{

@Override

public void mySpi(URL url, String name) {

System.out.println("This is S1 : "+name);

}

}

public class S2 implements SpiTest{

@Override

public void mySpi(URL url,String name) {

System.out.println("This is S2 : "+name);

}

}

在META-INF/dubbo下创建文件com.xx.dubbospi.SpiTest

S1=com.zf.xx.dubbospi.S1

S2=com.zf.xx.dubbospi.S2

在正常使用的时候可以通过 ExtensionLoader.getExtensionLoader(SpiTest.class).getExtension("S1")来获取SpiTest的某一个实现,但是如果在方法调用时不确定具体实现类怎么办?可以定义一个包装类SpiWrapper ,包装类不具体实现方法,只是根据参数获取对应的扩展对象来执行,根据传入的参数来获取到底时S1还是S2:

public class SpiWrapper implements SpiTest{

@Override

public void mySpi(URL url,String name) {

SpiTest spiTest = ExtensionLoader.getExtensionLoader(SpiTest.class).getExtension(url.getParameter("spi.test"));//通过参数指定需要加载的对象

spiTest.mySpi(url,name);

}

public static void main(String[] args) {

URL url = new URL("dubbo","123",999);//这里的URL是 org.apache.dubbo.common.URL

url = url.addParameter("spi.test","S2");

SpiWrapper spiWrapper = new SpiWrapper();

spiWrapper.mySpi(url,"tudou");

}

}

在SpiWrapper 中会根据url上的参数spi.test的值类决定到底取SpiTest的哪一个实现类,这样就实现的SPI的一个动态扩展。而在Dubbo中具体的使用需要先对SpiTest进行改造:

@SPIpublic interface SpiTest{

@Adaptive

void mySpi(URL url, String name);

}

在方法上增加注解 @Adaptive,Adaptive就是告诉Dubbo应该使用哪一个实现类来调用mySpi方法。实现逻辑就是通过约定在URL(key-value)中提取 key值,通过key值来决定实现类。比如我们使用 protocol为Dubbo,那么通过yml文件指定dubbo.protocol.name为dubbo,在URL上的格式就是 protocol=dubbo,后续执行服务流量交易导出 export的时候就会加载DubboProtocol来实现。

@SPI("dubbo") //默认dubbo

public interface Protocol {

@Adaptive

<T> Exporter<T> export(Invoker<T> invoker) throws RpcException;

}

配置文件

filter=org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper

listener=org.apache.dubbo.rpc.protocol.ProtocolListenerWrapper

mock=org.apache.dubbo.rpc.support.MockProtocol

dubbo=org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol

injvm=org.apache.dubbo.rpc.protocol.injvm.InjvmProtocol

http=org.apache.dubbo.rpc.protocol.http.HttpProtocol

rmi=org.apache.dubbo.rpc.protocol.rmi.RmiProtocol

hessian=org.apache.dubbo.rpc.protocol.hessian.HessianProtocol

org.apache.dubbo.rpc.protocol.webservice.WebServiceProtocol

thrift=org.apache.dubbo.rpc.protocol.thrift.ThriftProtocol

native-thrift=org.apache.dubbo.rpc.protocol.nativethrift.ThriftProtocol

memcached=org.apache.dubbo.rpc.protocol.memcached.MemcachedProtocol

redis=org.apache.dubbo.rpc.protocol.redis.RedisProtocol

rest=org.apache.dubbo.rpc.protocol.rest.RestProtocol

xmlrpc=org.apache.dubbo.xml.rpc.protocol.xmlrpc.XmlRpcProtocol

grpc=org.apache.dubbo.rpc.protocol.grpc.GrpcProtocol

registry=org.apache.dubbo.registry.integration.RegistryProtocol

service-discovery-registry=org.apache.dubbo.registry.client.ServiceDiscoveryRegistryProtocol

qos=org.apache.dubbo.qos.protocol.QosProtocolWrapper

再来看我们的例子:

public class SpiWrapper implements SpiTest{

@Override

public void mySpi(URL url,String name) {

//主要通过在Url上找到 spi.test 参数的值 , ExtensionLoader.getExtensionLoader(SpiTest.class).getExtension("S1")

SpiTest spiTest = ExtensionLoader.getExtensionLoader(SpiTest.class).getAdaptiveExtension();//通过url参数获取自适应对象

//SpiTest spiTest = ExtensionLoader.getExtensionLoader(SpiTest.class).getExtension(url.getParameter("spi.test"));

spiTest.mySpi(url,name);

}

public static void main(String[] args) {

URL url = new URL("dubbo","123",999);

url = url.addParameter("spi.test","S1");//指定url参数

SpiWrapper spiWrapper = new SpiWrapper();

spiWrapper.mySpi(url,"tudou");

}

}

通过指定URL的参数,就可以自动加载对应的扩展实现类。具体的ExtensionLoader源码分析,官网写的很详细,有兴趣可以看一下。

Dubbo源码中大量使用了SPI的动态扩展,如果不弄清楚,可能对学习源码会是一个比较大的阻碍。希望这篇文章能帮助大家进一步的理解SPI的自适应,在进行源码调试的时候,可以追踪到具体的实现类。

(0)

相关推荐

  • Dubbo和Zookeeper

    一.软件架构演进 软件架构的发展经历了由单体架构.垂直架构.分布式架构到流动计算架构的演进过程. 1.单一架构 当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本.此时,用于 ...

  • Dubbo 一篇文章就够了:从入门到实战

    一 为什么需要 dubbo 很多时候,其实我们使用这个技术的时候,可能都是因为项目需要,所以,我们就用了,但是,至于为什么我们需要用到这个技术,可能自身并不是很了解的,但是,其实了解技术的来由及背景知 ...

  • Dubbo常见题目

    前言 我会列举一些常见的 Dubbo 面试题,只会抓着重的,一些太简单的我就不提了. 不仅仅给你面试题的答案,也会剖析面试官问这个问题的原因,也就是他的内心活动. 想从你这里问出什么?想要什么答案?想 ...

  • JDK/Dubbo/Spring 三种 SPI 机制,谁更好?

    空无 写代码的渣渣鹏 昨天 来源:juejin.cn/post/6950266942875779108 SPI 全称为 Service Provider Interface,是一种服务发现机制.SPI ...

  • Java SPI 与 Dubbo SPI

    SPI(Service Provider Interface)是JDK内置的一种服务提供发现机制.本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类.这样可以在运行时,动 ...

  • 一、dubbo的注册中心以及服务注册源码剖析

    一.整体设计 dubbo整体设计以及调用用链路参照官网http://dubbo.apache.org/zh-cn/docs/dev/design.html 二.dubbo的注册中心 1.注册中心参照官 ...

  • 经济学CSSCI来源期刊与扩展版期刊(2021-2022版)

    日前,2021-2022年度的CSSCI来源期刊目录已完整发布."马经青年"现将经济学CSSCI来源期刊(71种,不包括台湾地区的3种)与扩展版期刊(28种)推送给各位同仁,方便各 ...

  • 更安全地扩展墙壁插座,而且轻巧易携带,ORICO魔方插座上手

    家里的插孔总有不够用的时候,像是到了夏天,我们就需要使用电蚊香一类的驱蚊工具,墙上要是还插着台灯.电视一类的电器,用起来就不方便了.这时候很多人应该都会用排插来解决问题,不过排插虽然好用,但是会多出一 ...

  • dr5修图扩展滤镜免费分享,无套路

    回复 "5"  可以下载. DR3/4/5.Beauty Retouch  是在Photoshop里录制的动作,通过软件转换成扩展在添加在Photoshop. 上面这个图就是制作D ...

  • 基于梯度阈值自适应处理的红外图像超分辨率重建

    0 引言 高分辨率成像是图像处理环节进行有效信息提取和分析的重要前提.然而,实际成像系统获取的图像空间分辨率往往不能满足信息处理的需求,这种现象在红外成像领域更为普遍[1]. 目前,国内外报道了大量超 ...

  • 《北航学报(社科版)》重归CSSCI扩展版来源期刊

    北航新闻网5月7日电(通讯员 杨丹阳)日前,在CSSCI公布的CSSCI(2021-2022)扩展版来源期刊目录中,<北航学报(社科版)>重新位列其中,这是时隔十年之后再次冲进C刊扩展版. ...

  • Azure上的Java:监视和扩展容器化的应用程序

    了解应用程序的运行状况至关重要.如果您的服务不可用,则可能会降低生产力并延误其他流程.您可以通过多种方式跟踪应用程序的可用性.AzureMonitor提供了一种收集和分析有关应用程序性能和事件的信息的 ...

  • CSSCI扩展(2021-2022年)扩展来源期刊 南大核心扩展版目录(完整版)

    中文社会科学引文索引(Chinese Social Sciences Citation Index,简称CSSCI)是由南京大学投资建设.南京大学中国社会科学研究评价中心开发研制的人文社会科学引文数据 ...