千家信息网

如何实现Dubbo的SPI自适应扩展

发表于:2025-01-19 作者:千家信息网编辑
千家信息网最后更新 2025年01月19日,这篇文章主要讲解了"如何实现Dubbo的SPI自适应扩展",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"如何实现Dubbo的SPI自适应扩展"吧!先定义
千家信息网最后更新 2025年01月19日如何实现Dubbo的SPI自适应扩展

这篇文章主要讲解了"如何实现Dubbo的SPI自适应扩展",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"如何实现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.S1S2=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") //默认dubbopublic interface Protocol {@Adaptive     Exporter export(Invoker invoker) throws RpcException;}配置文件filter=org.apache.dubbo.rpc.protocol.ProtocolFilterWrapperlistener=org.apache.dubbo.rpc.protocol.ProtocolListenerWrappermock=org.apache.dubbo.rpc.support.MockProtocoldubbo=org.apache.dubbo.rpc.protocol.dubbo.DubboProtocolinjvm=org.apache.dubbo.rpc.protocol.injvm.InjvmProtocolhttp=org.apache.dubbo.rpc.protocol.http.HttpProtocolrmi=org.apache.dubbo.rpc.protocol.rmi.RmiProtocolhessian=org.apache.dubbo.rpc.protocol.hessian.HessianProtocolorg.apache.dubbo.rpc.protocol.webservice.WebServiceProtocolthrift=org.apache.dubbo.rpc.protocol.thrift.ThriftProtocolnative-thrift=org.apache.dubbo.rpc.protocol.nativethrift.ThriftProtocolmemcached=org.apache.dubbo.rpc.protocol.memcached.MemcachedProtocolredis=org.apache.dubbo.rpc.protocol.redis.RedisProtocolrest=org.apache.dubbo.rpc.protocol.rest.RestProtocolxmlrpc=org.apache.dubbo.xml.rpc.protocol.xmlrpc.XmlRpcProtocolgrpc=org.apache.dubbo.rpc.protocol.grpc.GrpcProtocolregistry=org.apache.dubbo.registry.integration.RegistryProtocolservice-discovery-registry=org.apache.dubbo.registry.client.ServiceDiscoveryRegistryProtocolqos=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");    }}

感谢各位的阅读,以上就是"如何实现Dubbo的SPI自适应扩展"的内容了,经过本文的学习后,相信大家对如何实现Dubbo的SPI自适应扩展这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

0