美文网首页
【dubbo源码】6.dubbo的spi机制

【dubbo源码】6.dubbo的spi机制

作者: 天还下着毛毛雨 | 来源:发表于2021-07-03 11:50 被阅读0次
Dubbo的SPI由JDK标准的SPI加强而来

Dubbo 改进了 JDK 标准的 SPI 的以下问题:

  • JDK 标准的 SPI 会一次性实例化扩展点所有实现,如果有扩展实现初始化很耗时,但如果没用上也加载,会很浪费资源。
  • 如果扩展点加载失败,连扩展点的名称都拿不到了。比如:JDK 标准的 ScriptEngine,通过 getName() 获取脚本类型的名称,但如果 RubyScriptEngine 因为所依赖的 jruby.jar 不存在,导致 RubyScriptEngine 类加载失败,这个失败原因被吃掉了,和 ruby 对应不起来,当用户执行 ruby 脚本时,会报不支持 ruby,而不是真正失败的原因。
  • 增加了对扩展点 IoC 和 AOP 的支持,一个扩展点可以直接 setter 注入其它扩展点。
约定方式:

在jar包内,放置SPI配置文件 META-INF/dubbo/接口全限定名,内容为配置名=扩展实现类全限定名,多个实现类用换行符分隔。

image

Dubbo的加载拓展类Api : ExtensionLoader

Dubbo提供了对Spi配置类的加载api,在源码中也是使用这种Api来获取指定的拓展类实例

比如ServiceConfig :

image

使用示例 :

api接口 :

AdaptiveApi :

@SPI("spring")
public interface AdaptiveApi {
    void doSomething();
}

多个实现类 :
@Activate(value = "mybatis1",group = "mybatis")
public class Mybatis1Adaptive implements AdaptiveApi {
    @Override
    public void doSomething() {
        System.out.println("mybatis1");
    }
}
@Activate(value = "mybatis",group = "mybatis")
public class MybatisAdaptive implements AdaptiveApi {
    @Override
    public void doSomething() {
        System.out.println("mybatis");
    }
}
@Adaptive
@Activate(value = "rabbit", group = "rabbit")
public class RabbitAdaptive implements AdaptiveApi {
    @Override
    public void doSomething() {
        System.out.println("rabbit");
    }
}
@Activate(value = "spring",group = "spring")
public class SpringAdaptive implements AdaptiveApi {
    @Override
    public void doSomething() {
        System.out.println("spring");
    }
}

spi配置文件:
META-INF/dubbo/com.lb.dubbo_api.dubbo_spi.AdaptiveApi
spring=com.lb.dubbo_api.dubbo_spi.SpringAdaptive
rabbit=com.lb.dubbo_api.dubbo_spi.RabbitAdaptive
mybatis=com.lb.dubbo_api.dubbo_spi.MybatisAdaptive
mybati1=com.lb.dubbo_api.dubbo_spi.Mybatis1Adaptive
测试api :
public class SpiTest {

    @Test
    public void testSpi() {
        // 获取默认的类型实例 接口上@SPI("spring")指定的key,到com.lb.dubbo_api.dubbo_spi.AdaptiveApi文件里去对应的类型
        AdaptiveApi defaultExtension = ExtensionLoader.getExtensionLoader(AdaptiveApi.class).getDefaultExtension();
        System.out.println(defaultExtension);

        // 获取AdaptiveApi实现类中带有@Adaptive注解的类,超出一个则报错 More than 1 adaptive class found: java.lang.Class, java.lang.Class
        AdaptiveApi adaptiveExtension = ExtensionLoader.getExtensionLoader(AdaptiveApi.class).getAdaptiveExtension();
        adaptiveExtension.doSomething();

        // 获取配置文件中所有的key,除了@Adaptive注解
        Set<String> supportedExtensions = ExtensionLoader.getExtensionLoader(AdaptiveApi.class).getSupportedExtensions();
        for (String loadedExtension : supportedExtensions) {
            System.out.println(loadedExtension);
        }

        // 获取接口上@SPI("spring")指定的key
        Set<String> loadedExtensions = ExtensionLoader.getExtensionLoader(AdaptiveApi.class).getLoadedExtensions();
        for (String loadedExtension : loadedExtensions) {
            System.out.println(loadedExtension);
        }

        // 获取已加载的实现类的实例,只有接口上@SPI("spring")配置的这个才可以获取到
        AdaptiveApi spring = ExtensionLoader.getExtensionLoader(AdaptiveApi.class).getLoadedExtension("spring");
        spring.doSomething();

        // 获取group为mybatis的类,如果实现类上@Activate配置了value属性,则会根据url的key与value进行匹配,匹配到的才会返回
        // 如果group为mybatis的类的@Activate都没有配置,就会全部返回
        URL url =  URL.valueOf("test://localhost:8081");
        List<AdaptiveApi> mybatis = ExtensionLoader.getExtensionLoader(AdaptiveApi.class).getActivateExtension(url, new String[]{}, "mybatis");
        System.out.println(mybatis.size());

        // 获取group为mybatis的类,如果实现类上@Activate配置了value属性,则会根据url的param与value进行匹配,匹配到的才会返回
        // 先分组匹配,再url匹配
        URL url1 =  URL.valueOf("test://localhost:8081");
        URL url2 = url1.addParameter("mybatis2", "...");
        List<AdaptiveApi> mybatis1 = ExtensionLoader.getExtensionLoader(AdaptiveApi.class).getActivateExtension(url2, new String[]{}, "mybatis");
        System.out.println(mybatis1.size());

        // 获取group为mybatis的类,如果实现类上@Activate配置了value属性,则会根据url的param与value进行匹配,匹配到的才会返回
        // 先分组匹配,再url匹配,才会返回getActivateExtension的第二个字符串数组参数指定的key的类型实例
        URL url3 = URL.valueOf("test://localhost:8081").addParameter("mybatis2", "...");
        List<AdaptiveApi> springs = ExtensionLoader.getExtensionLoader(AdaptiveApi.class).getActivateExtension(url3, new String[]{"spring"}, "mybatis");
        System.out.println(springs.size());
    }
}

相关文章

  • 【dubbo源码】6.dubbo的spi机制

    Dubbo的SPI由JDK标准的SPI加强而来 Dubbo 改进了 JDK 标准的 SPI 的以下问题: JDK ...

  • Dubbo SPI机制分析【二】

    title: Dubbo SPI机制分析【二】tags: Dubbo,SPI,源码grammar_cjkRuby:...

  • Dubbo SPI机制分析【一】

    title: Dubbo SPI机制分析tags: Dubbo,SPI,源码grammar_cjkRuby: tr...

  • Dubbo第三天

    5. SPI 机制原理 因为dubbo 框架是建立的 SPI 机制上,因此在探寻 dubbo 框架源码前,我们需要...

  • JAVA SPI解析

    JAVA SPI解析 在阅读Dubbo源码时发现Dubbo针对java的spi机制做了扩展。那么spi究竟是什么呢...

  • dubbo源码解析之SPI扩展机制(一)

    源码分析基于dubbo 2.7.1-release 看dubbo源码不得不了解dubbo spi机制,因为你常常看...

  • Dubbo SPI机制

    一、前言 学习dubbo源码时,Dubbo的SPI机制必须先了解,不然阅读Dubbo源码会非常困难 二、使用 1....

  • dubbo的spi机制

    dubbo的spi机制 dubbo的扩展点加载机制源自于java的spi扩展机制。那么,何为java的spi扩展机...

  • dubbo原理:SPI机制(二)

    在上一篇:SPI机制(一)中研究了Dubbo SPI的自适应原理;SPI机制(二)中我们来研究下Dubbo SPI...

  • dubbo 原理解析

    rpc 流程:1、dubbo spi 中的 warp 机制,实现类增强2、dubbo spi 中的自适应机制,通过...

网友评论

      本文标题:【dubbo源码】6.dubbo的spi机制

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