一、Java SPI vs Dubbo SPI
JDK 标准的 SPI 会一次性实例化扩展点所有实现,如果有扩展实现初始化很耗时,但如果没用上也加 载,会很浪费资源
如果有扩展点加载失败,则所有扩展点无法使用
提供了对扩展点包装的功能(Adaptive),并且还支持通过set的方式对其他的扩展点进行注入
二、介绍
1 dubbo中大量的使用了SPI来作为扩展点,通过实现同一接口的前提下,可以进行定制自己的实现类。 比如比较常见的协议,负载均衡,都可以通过SPI的方式进行定制化,自己扩展。Dubbo中已经存在的 所有已经实现好的扩展点。
2 Dubbo中默认提供的负载均衡策略。
三、Demo 基于第一节实现
1 项目搭建
2 api 模块依赖引入
<dependencies><dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo</artifactId><version>3.0.2.1</version></dependency></dependencies>
3 指定默认实现 和 扩展注解
Dubbo中的Adaptive功能,主要解决的问题是如何动态的选择具体的扩展点。通过 getAdaptiveExtension 统一对指定接口对应的所有扩展点进行封装,通过URL的方式对扩展点来进行 动态选择。 (dubbo中所有的注册信息都是通过URL的形式进行处理的。)
4 扩展实现
5 SPI 配置
6 测试类
1 自定义的URL
public class DubboAdaptiveMain {public static void main(String[] args) {URL url = URL.valueOf("test://localhost/hello?hello.service=animal");final HelloService adaptiveExtension = ExtensionLoader.getExtensionLoader(HelloService.class).getAdaptiveExtension();String sayHello = adaptiveExtension.sayHello(url);System.out.println(sayHello);}}

2 使用默认指定的Service
public class DubboAdaptiveMain {public static void main(String[] args) {URL url = URL.valueOf("test://localhost/hello");final HelloService adaptiveExtension = ExtensionLoader.getExtensionLoader(HelloService.class).getAdaptiveExtension();String sayHello = adaptiveExtension.sayHello(url);System.out.println(sayHello);}}

注意:
1 因为在这里只是临时测试,所以为了保证URL规范,前面的信息均为测试值即可。
2 关键的点在于 hello.service 参数,这个参数的值指定的就是具体的实现方式。
3 hello.service 是因为这个接口的名称,其中后面的大写部分被dubbo自动转码为 . 分割。
4 通过 getAdaptiveExtension 来提供一个统一的类来对所有的扩展点提供支持(底层对所有的扩展 点进行封装)。
5 调用时通过参数中增加 URL 对象来实现动态的扩展点使用。
6 如果URL没有提供该参数,则该方法会使用默认在 SPI 注解中声明的实现。


