9.Dubbo SPI机制解读(辅助Java SPI机制理解)

[传送门]  Java SPI,请参考:Java SPI机制解读 && 源码解读,建议:先看完Java SPI后,再来了解Dubbo SPI ^_^

[传送门]  JDK动态代理,请参考:JDK动态代理     如需了解JDK动态代理和Cglib动态代理区别,附:Cglib动态代理


1.什么是Dubbo SPI

        Dubbo SPI,是对Java SPI机制的扩展,与Java SPI机制类似,原理相同,都是一种动态服务发现机制,来实现相关的操作。Dubbo框架就是通过 Dubbo SPI 机制,从而实现 Dubbo 自定义协议、Dubbo 自定义路由......等很多模块的自定义。如想了解决SPI机制的原理实现原理,请点击本文开篇传送门,来做进一步了解,然后在回来瞅这篇

2.Dubbo SPI与Java SPI的不同

Dubbo SPI

    ①配置文件存放路径不同:META-INF/dubbo/、META-INF/dubbo/internal/、META-INF/services/(3种)

    ②配置文件中内容不同:KV键值对形式(key=value形式)

    ③增加了Spring IOC 和 AOP 的支持

Java SPI

    ①配置文件存放路径不同:META-INF/services/(1种)

    ②配置文件中内容不同:接口实现类的全限定名

3.Dubbo SPI的扩展   

       由于文件中内容的不同,也就直接导致了Dubbo中无法直接使用JDK中提供的ServiceLoader类,来动态装载实现模块 。与之对应,Dubbo中提供了ExtensionLoader类。ExtensionLoader是扩展点载入器,用于载入Dubbo中的各种可配置组件,比如:动态代理方式(ProxyFactory)、负载均衡策略(LoadBalance)、RCP协议(Protocol)、拦截器(Filter)、容器类型(Container)、集群方式(Cluster)和注册中心类型(RegistryFactory)等。

       Dubbo为了应对各种场景,它的所有内部组件都是通过这种SPI的方式来管理的,这也是为什么Dubbo需要将服务提供者配置文件设计成KV键值对形式,这个K就是我们在Dubbo配置文件或注解中用到的K,Dubbo直接通过服务接口(上面提到的ProxyFactory、LoadBalance、Protocol、Filter等)和配置的K从ExtensionLoader拿到服务提供的实现类

       同时,由于Dubbo使用了URL总线的设计即很多参数通过URL对象来传递,在实际中,具体要用到哪个值,可以通过URL中的参数值来指定。(在下面源码分析中,你便会看到URL总线的体现)

4.Dubbo SPI实例

      在dubbo中,支持多种协议。如:默认的dubbo协议、hessian协议、redis协议、webservice协议、rmi协议等等。但是如果我想用我自己编写的协议,那么这种扩展就得用Dubbo的SPI机制来实现了。

       Dubbo框架相当于官方,它为我们提供了协议扩展的接口Protocol,Dubbo官方也为我们提供了上面协议的具体实现。如果我们需要使用自己的协议来发布服务,那么我们便需要实现该接口,重写接口里面的方法,即可实现用我们自己的协议来发布服务了

①创建一个MyProtocol类,实现Protocol接口,重写该接口的方法

package com.test.dubbo;

import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.rpc.Exporter;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Protocol;
import com.alibaba.dubbo.rpc.RpcException;
/**
 * 自定义的协议
 * 每个接口重写方法是什么意思,参见 5.Dubbo SPI 源码解析,有详细解析
 * 重写Protocol接口的方法(本例仅重写了一个getDefaultPort方法)
 */
public class MyProtocol implements Protocol {

    @Override
    public int getDefaultPort() {
        return 8789;
    }

    @Override
    public  Exporter export(Invoker invoker) throws RpcException {
        return null;
    }

    @Override
    public  Invoker refer(Class aClass, URL url) throws RpcException {
        return null;
    }

    @Override
    public void destroy() {

    }
}

②约定实现

        在resources目录下,新建META-INF/dubbo(或者META-INF/dubbo/internalMETA-INF/services)目录。然后新建一个以"接口全限定名"为文件名的文件,本例为com.alibaba.dubbo.rpc.Protocol;文件内容为KV结构(K为自定义,V为实现类的全限定名,本例为com.test.dubbo.MyProtocol

9.Dubbo SPI机制解读(辅助Java SPI机制理解)_第1张图片

③使用 ExtensionLoader 类来加载配置文件中指定的实现

package com.test.dubbo;

import com.alibaba.dubbo.common.extension.ExtensionLoader;
import com.alibaba.dubbo.rpc.Protocol;
import java.io.IOException;

public class testHello {

    public static void main(String[] args) throws IOException {
        //通过getExtension(String name),可以获得自定义的指定名称为key的协议
        Protocol myProtocol = ExtensionLoader.getExtensionLoader(Protocol.class).getExtension("myProtocol");
        System.out.println(myProtocol.getDefaultPort());//输出:8789
        
        //通过getDefaultExtension(),可以获得Dubbo框架默认的协议
        Protocol defaultProtocol = ExtensionLoader.getExtensionLoader(Protocol.class).getDefaultExtension();
        System.out.println(defaultProtocol.getDefaultPort());//输出:20880
    }
}

通过如上,我们便能够加载自己定义的协议了。从上面,我们也能够知道Dubbo框架默认协议为dubbo协议,端口为20880

Dubbo SPI机制介绍 && Dubbo SPI实例介绍,到此为止

如果本文对你有所帮助,那就给我点个赞呗 ^_^ 

End

 

你可能感兴趣的:(Dubbo)