dubbo SPI使用:@SPI 与 @Adaptive

dubbo中使用spi除了配置文件外还需要有@SPI和@Adaptive注解,这两个注解中都可以设置参数,且@Adaptive注解可以设置在方法上也可以设置在类上。下面我们来卡一下他的具体使用规则。

1、引入dubbo依赖:

<dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>dubbo</artifactId>
   <version>2.6.x</version>
</dependency>

2、创建接口、实现类、配置文件:

@SPI("impl1")
public interface SpiService {

    @Adaptive
    String spiTest1(URL url);

    String spiTest2(URL url);

}

实现类3个:

public class SpiServiceImpl1 implements SpiService {
    @Override
    public String spiTest1(URL url) {
        return " SpiServiceImpl1 -->  test1";
    }

    @Override
    public String spiTest2(URL url) {
        return " SpiServiceImpl1 -->  test2";
    }
}



public class SpiServiceImpl2 implements SpiService {
    @Override
    public String spiTest1(URL url) {
        return " SpiServiceImpl2 -->  test1";
    }

    @Override
    public String spiTest2(URL url) {
        return " SpiServiceImpl2 -->  test2";
    }
}


public class SpiServiceImpl3 implements SpiService {
    @Override
    public String spiTest1(URL url) {
        return " SpiServiceImpl3 -->  test1";
    }

    @Override
    public String spiTest2(URL url) {
        return " SpiServiceImpl3 -->  test2";
    }
}

3、配置文件:META-INF/dubbo/internal/cn.zsm.dubbo.service.SpiService

配置文件的路径可以有三种: META-INF/dubbo/internal 、 META-INF/dubbo   、META-INF/services

impl1=cn.zsm.dubbo.dubboprovider.service.impl.SpiServiceImpl1
impl2=cn.zsm.dubbo.dubboprovider.service.impl.SpiServiceImpl2
impl3=cn.zsm.dubbo.dubboprovider.service.impl.SpiServiceImpl3

4、编写测试类

    @Test
    void test1() {
        ExtensionLoader<SpiService> extensionLoader = ExtensionLoader.getExtensionLoader(SpiService.class);
        SpiService adaptiveExtension = extensionLoader.getAdaptiveExtension();
        URL url = URL.valueOf("test://localhost/test");
        System.out.println(adaptiveExtension.spiTest1(url));
    }

输出:  调用impl1

这里我们是使用了@SPI注解中的默认的扩展点 "impl1", 下面我们不改变业务代码,在测试类中的URL参数中指定扩展点:

5、URL指定扩展点:

    @Test
    void test1() {
        ExtensionLoader<SpiService> extensionLoader = ExtensionLoader.getExtensionLoader(SpiService.class);
        SpiService adaptiveExtension = extensionLoader.getAdaptiveExtension();
        // url中指定扩展点
        URL url = URL.valueOf("test://localhost/test?cn.zsm.dubbo.service.SpiService=impl2"); 
        System.out.println(adaptiveExtension.spiTest1(url)); 
    }

执行结果:  调用impl2

6、不改变其他条件, 在SpiServiceImpl3  类上添加注解: @Adaptive

输出结果:  调用impl3

7、不改变其他条件,在SpiService 接口的 spiTest1方法的@Adaptive注解中添加属性值:

输出结果: 调用impl3

8、去掉impl3的@Adaptive注解

输出结果:调用impl1

9、如果我们在SpiService 接口中,让@Adaptive的值与@SPI的值不同:

输出结果: 调用impl1

10、错误示范, spiTest2 上没有@Adaptive注解,我们在测试类中调用它看会怎样: 

输出结果:

public java.lang.String spiTest2(com.alibaba.dubbo.common.URL arg0) 
{
throw new UnsupportedOperationException("method public abstract java.lang.String 
cn.zsm.dubbo.service.SpiService.spiTest2(com.alibaba.dubbo.common.URL) of interface 
cn.zsm.dubbo.service.SpiService is not adaptive method!");
}

前面爆出一段错误,spiTest2 is not adaptive method , 输出依然是test1。 可以看出没有@Adaptive注解的方法不能被扩展。

综合上面几个例子可以看出: 

  1. dubbo要使用SPI扩展,被扩展的接口必须要@SPI注解, 方法必须有@Adaptive注解
  2. 扩展类的优先级: @Adaptive标记的扩展类 > URL中指定的扩展类 > @SPI 注解中指定的扩展类
  3. 如果@SPI注解指定了扩展类, 方法的@Adaptive注解中也指定了扩展类,@SPI中指定的扩展类会覆盖URL中指定的扩展类; 且@Adaptive 与@SPI指定的扩展类不同时,会使用@SPI中指定的扩展类
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值