美文网首页
(SPI)2.dubbo spi

(SPI)2.dubbo spi

作者: 无聊之园 | 来源:发表于2021-10-26 14:48 被阅读0次

    一、dubbo spi效果简单描述

    比如,你写了一个工具jar包,为了方便扩展,代码里以接口的方式调用,没有具体的实现类,下层应用只需要再mate-inf里以key-value对的形式指定好具体的实现类,然上层应用depend一下就能以这个实现类运行,达到很好的扩展性效果。

    一、dubbo为什么要自己实现spi呢?

    1、因为,dubbo需要一个接口提供多个实现类,然后通过注解的方式或者其他方式,指定使用哪个实现类,而java se 的spi不是key-value对的形式。
    比如,它的/META_INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol文件内容是:
    dubbo=com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol
    http=com.alibaba.dubbo.rpc.protocol.http.HttpProtocol
    hessian=com.alibaba.dubbo.rpc.protocol.hessian.HessianProtocol
    以properties的方式,对实现类提供了一个标识符,然后通过@SPI("dubbo")这样的方式,实现加载指定的实现类,而这个方式,是java自带的spi做不到的。
    2、dubbo的spi有adapter spi来达到根据不同参数使用不同实现类的动态效果,有activate根据不同条件获取不同实现类的效果。这些丰富的效果是javase spi不具备的。
    3、dubbo的spi的ExtendsionFactory就是基于jdk的spi的。
    4、dubbo的spi,按需实例化,不想jdk的全部实例化。
    5、dubbo的spi有ioc的功能。

    二、dubbo spi的三种

    1.普通的获取扩展类。

    Protocol dubbo = ExtensionLoader.getExtensionLoader(Protocol.class)
                    .getExtension("dubbo");
    
    @SPI("dubbo")
    public interface Protocol 
    
    在指定目录下(dubbo会扫描3个目录)添加指定规则的文件,描述接口的各个实现类
    /META_INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol
    dubbo=org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol
    
    

    2.自适应扩展点
    通过如下方式获取自适应扩展接口实现类。

    Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
    

    有两种:
    1)@Adaptive 加在类上。显示指定这个类是自适应类,通过getAdaptiveExtension方法获取到的就是这个类。
    2)@Adaptive加在方法上。dubbo会产生一个代理类(默认是javasisit动态编码产生)。getAdaptiveExtension方法获取到的就是这个代理类。代理类会根据传参,通过URL参数动态决定调用哪一个实现类的这个方法。

    @SPI("dubbo")  
    public interface Protocol {  
        int getDefaultPort();  
        @Adaptive  
        <T> Exporter<T> export(Invoker<T> invoker) throws RpcException;  
        @Adaptive  
        <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;  
        void destroy();  
    } 
    

    3.自动激活扩展点
    能够根据传参,来指定具体激活获取到哪些实现类。

    @Activate(group = {CONSUMER, PROVIDER}, value = CACHE_KEY)
    public class CacheFilter implements Filter
    

    自动激活扩展点可以根据url参数,指定加载激活哪些实现类。
    activate有两个条件指定,1.group。可以是consumer、provider。2.value。

    调用方式:

           ExtensionLoader<Filter> loader = ExtensionLoader.getExtensionLoader(Filter.class);
    /*  
            URL url = new URL("", "", 0);
            url = url.addParameter("cache", "123");
            // 参数url中有cache这个key,这里就能获取到CacheFilter
            List<Filter> filters = loader.getActivateExtension(url, "zhangsan");
    */
            URL url = new URL("", "", 0);
            url = url.addParameter("ab", "cache");
          // 传参ab,会根据这个参数,从url中获取具体的值,得到cache,所以这里也能获取到cacheFilter
            List<Filter> filters = loader.getActivateExtension(url, "ab");
            System.out.println(filters);
            System.out.println(filters.size());
    
    4.题外话

    javasisit只是编译和加载,不能重新加载类,所以不能达到:
    @ApiOperator("name")
    @NotBlank("name不能魏空")
    @Length(max = 20, value = "name不能超过20")
    替换为
    @MyNotBlankLengthApi("name", max = 40)
    的效果。

    从ExtensionLoader的源码中可以看出:
    每个方法开头都会对参数进行合法性校验,而我实际开发中,为了代码简洁,减少if、else,往往会约定大于配置的那种思想,默认这个参数就是合法的,因为我觉得,代码都是自己写的,都是内部调用,代码文档也会说清楚,如果为了参数校验,增加很多if、else显得多余。但是dubbo是通用工具类,所以要做好这部分的配置。

    (写出来的目的是,希望隔了很久之后,看了笔记还能回想起来)

    相关文章

      网友评论

          本文标题:(SPI)2.dubbo spi

          本文链接:https://www.haomeiwen.com/subject/qmmedltx.html