dubbo之扩展点

305 阅读2分钟

dubbo Spi

jdk spi

jdk的spi机制是通过ServiceLoader.load指定的class,主要做了如下几个工作:

  1. META-INF/services文件夹下查找名称为class全限定名的文件
  2. 读取文件内容,拿到实现类的全限定名
  3. 通过反射,创建所有实现类的实例

dubbo spi

通过 ExtensionLoader,我们可以加载指定的实现类。Dubbo SPI 所需的配置文件需放置在 META-INF/dubbo 路径下,配置内容如下:

optimusPrime = org.apache.spi.OptimusPrime
bumblebee = org.apache.spi.Bumblebee

与 Java SPI 实现类配置不同,Dubbo SPI 是通过键值对的方式进行配置,这样我们可以按需加载指定的实现类。另外,在测试 Dubbo SPI 时,需要在 Robot 接口上标注 @SPI 注解。

dubbo 自适应spi

有些拓展并不想在框架启动阶段被加载,而是希望在拓展方法被调用时,根据运行时参数进行加载。具体实现可总结如下:

  1. 给拓展接口生成代理功能的代码
  2. 然后通过 javassist 或 jdk 编译这段代码,得到代理类
  3. 代理类中的目标类根据注解@adaptive的value获得目标类的名称
  4. 根据上一步得到的名称通过dubbo spi机制去加载对应的目标类

区别

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

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