dubbo的SPI扩展实现原理简解

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/a158123/article/details/78785260

Java的SPI简介

Java中的SPI是通过接口+配置文件实现动态加载实现,使用方法及原理如下:
1. 创建SPI需要的接口,其实就是常见的接口文件
2. 实现创建的接口
3. 如果是Java项目,则在src下增加META-INF/services目录;如果是Maven项目则在src/main/resources下增加META-INF/services目录
4. 在META-INF/services创建一个以接口的*全限定名(包含完整包名的类名)为文件名的文件,在这个文件中添加接口实现类的全限定名。
5. 使用java.util.ServiceLoader类的load方法加载以接口的全限定名为文件名的文件声明的服务,使用迭代器(java.util.ServiceLoader的iterator方法)遍历。

PS: java.util.ServiceLoader只会在META-INF/services目录下加载配置是因为这个类中已经声明了加载的前缀为META-INF/services

dubbo中的SPI

ExtensionLoader

在dubbo中也参考Java的SPI实现了自己的SPI,其中核心类就是com.alibaba.dubbo.common.extension.ExtensionLoader。该类提供了SPI的配置解析和动态加载实现类

ExtensionLoader规定了dubbo本身的SPI扩展点配置文件放在dubbo.jar的META-INF/dubbo/internal目录下,文件名要求为全限定接口名,文件内容为配置名=扩展实现类全限定名,多个实现类用换行符分隔。

同时ExtensionLoader也规定了开发者自行的扩展会去META-INF/dubbo目录下检索开发者的实现。

ExtensionFactory

com.alibaba.dubbo.common.extension.ExtensionFactory是获取ExtensionLoader实例的工厂接口,内部只有一个获取扩展点的抽象方法。

dubbo内部只有3个ExtensionFactory的实现类,可以在duubo.jar的META-INF/dubbo/internal/com.alibaba.dubbo.common.extension.ExtensionFactory文件中找到,内容如下:

adaptive=com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory
spi=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory
spring=com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory

其中AdaptiveExtensionFactory是适配器扩展点工厂,SpiExtensionFactory是SPI扩展点工厂,SpringExtensionFactory是Spring扩展点工厂。

AdaptiveExtensionFactory管理其他的扩展点工厂,包括SpiExtensionFactorySpringExtensionFactory

自定义扩展

  1. 实现对应SPI扩展接口
  2. 如果是Java项目,则在src下增加META-INF/dubbo目录;如果是Maven项目则在src/main/resources下增加META-INF/dubbo目录
  3. 在新增的目录下添加文件,文件名为SPI扩展接口的全限定名
  4. 在新增的文件中添加配置名=扩展实现类全限定名,这里的配置名可以理解理解为键值对中的key或者是类似Spring中Bean的ID,而后面的扩展实现类全限定名则是实现,对应的是键值对中的value或者是Bean中class。
  5. 在dubbo的配置文件中对应的配置中使用你的配置名。

JAVA的SPI和dubbo的SPI的区别:

以下是官网的内容:

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

原文地址:http://dubbo.io/books/dubbo-dev-book/SPI.html

简单来说就是以下三点:
1. 支持懒加载(延迟加载)
2. 异常处理优化
3. 支持AOP

展开阅读全文

没有更多推荐了,返回首页