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

2021-07-03  本文已影响0人  天还下着毛毛雨
Dubbo的SPI由JDK标准的SPI加强而来

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

约定方式:

在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());
    }
}
上一篇 下一篇

猜你喜欢

热点阅读