目录
Dubbo中的Adaptive功能,主要解决的问题是如何动态的选择具体的扩展点。
通过getAdaptiveExtension 统一对指定接口对应的所有扩展点进行封装,通过URL的方式对扩展点来进行动态选择。 (dubbo中所有的注册信息都是通过URL的形式进行处理的。)
1、dubbo-spi-demo-api
创建接口。
- 在sayHello方法上增加 Adaptive 注解,并且在参数中提供URL参数。注意这里的URL参数的类为 org.apache.dubbo.common.URL
- 其中@SPI可以指定一个字符串参数,用于指明该SPI的默认实现。不指定默认的话,如果方法调用时也不指定,会报错。如果这里指定了,方法调用时不指定,调用的是默认的。
package com.lagou.service;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.Adaptive;
import org.apache.dubbo.common.extension.SPI;
@SPI("dog")
public interface HelloService {
@Adaptive
String sayHello(URL url);
}
2、dubbo-spi-demo-impl
①引用api
<dependencies>
<dependency>
<groupId>com.lagou</groupId>
<artifactId>dubbo-spi-demo-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
②定义两个实现类
package com.lagou.service.impl;
import com.lagou.service.HelloService;
import org.apache.dubbo.common.URL;
public class DogHelloService implements HelloService {
@Override
public String sayHello(URL url) {
return "wang wang";
}
}
package com.lagou.service.impl;
import com.lagou.service.HelloService;
import org.apache.dubbo.common.URL;
public class HumanHelloService implements HelloService {
@Override
public String sayHello(URL url) {
return "hello 你好";
}
}
③配置
在resources\META-INF\dubbo下创建文件
【com.lagou.service.HelloService】
human=com.lagou.service.impl.HumanHelloService
dog=com.lagou.service.impl.DogHelloService
3、dubbo-spi-demo-main
①引用上面两个demo
<dependencies>
<dependency>
<groupId>com.lagou</groupId>
<artifactId>dubbo-spi-demo-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.lagou</groupId>
<artifactId>dubbo-spi-demo-impl</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
②测试
package com.lagou;
import com.lagou.service.HelloService;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.ExtensionLoader;
public class DubboAdaptiveMain {
public static void main(String[] args) {
URL url = URL.valueOf("test://localhost/hello?hello.service=human");
// URL url = URL.valueOf("test://localhost/hello?hello.service=dog");
HelloService adaptiveExtension = ExtensionLoader.getExtensionLoader(HelloService.class).getAdaptiveExtension();
String result = adaptiveExtension.sayHello(url);
System.out.println("result:" + result);
}
}
}
url配置方式:
- URL.valueOf中指定
其中,human
,对应MTEA-INF中定义内容的key
URL url = URL.valueOf("test://localhost/hello?hello.service=human");
- 定义接口类中指定
URL url = URL.valueOf("test://localhost/hello");
对应的接口定义如下:
@SPI("dog")
public interface HelloService {
@Adaptive
String sayHello(URL url);
}
-
若运行时的URL.valueOf中不指定,那么在此接口类中你那个必须指定默认
@SPI("dog")
,否则运行会报错
-
若@SPI中指定的和url中指定的不一致,则以url中的为准
③注意:
- 因为在这里只是临时测试,所以为了保证URL规范,前面的信息均为测试值即可,关键的点在于hello.service (HelloService)参数,这个参数的值指定的就是具体的实现方式。关于为什么hello.service ?是因为这个接口的名称是(HelloService),其中后面的大写部分被dubbo自动转码为 . 分割。
- 通过 getAdaptiveExtension 来提供一个统一的类来对所有的扩展点提供支持(底层对所有的扩展点进行封装)。
- 调用时通过参数中增加 URL 对象来实现动态的扩展点使用。
- 如果URL没有提供该参数,则该方法会使用默认在 SPI 注解中声明的实现。