文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

请问Dubbo的SPI机制是啥啊?

2024-12-02 21:55

关注

这又是什么呢,这个可以很好的支持一些有特殊需求的三方的接入,可以自定义扩展,自主定制二次开发,良好的扩展性对于框架来说是很重要的。

简单了解下SPI,全称为 Service Provider Interface,是一种服务发现机制。

它通过在ClassPath路径下的META-INF/services文件夹查找文件,自动加载文件里所定义的类。这一机制为很多框架扩展提供了可能,比如在Dubbo、JDBC中都使用到了SPI机制。

举个例子,比如你有个接口,现在这个接口有 3 个实现类,那么在系统运行的时候对这个接口到底选择哪个实现类呢?这就需要SPI了,需要根据指定的配置或者是默认的配置,去找到对应的实现类加载进来,然后用这个实现类的实例对象。

Java中JDK自身实现了SPI机制,基于策略模式来实现动态加载的机制 。我们在程序只定义一个接口,具体的实现交个不同的服务提供者;在程序启动的时候,读取配置文件,由配置确定要调用哪一个实现。

但是呢,存在一定的缺点,比如不能按照需要加载,会一次性加载所有可用的扩展点,很多是不需要的,会浪费系统资源;不支持AOP和依赖注入,实现类的方式也不够灵活,只能通过 Iterator 形式获取。

你不够强,或者说你做的不符合我的需求,我就替换你。

于是呢,dubbo重新实现了一套功能更强的 SPI 机制, 支持了AOP与依赖注入,并且 利用缓存提高加载实现类的性能,同时支持实现类的灵活获取。

Java中的SPI

Java中JDK自身实现了SPI机制,基于策略模式来实现动态加载的机制 。我们在程序只定义一个接口,具体的实现交个不同的服务提供者;在程序启动的时候,读取配置文件,由配置确定要调用哪一个实现。

首先,我们需要定义一个接口,SPIService。

  1. public interface SPIService { 
  2.     void execute(); 

然后,定义两个实现类,没别的意思,只输入一句话。‍

  1. public class SpiImpl1 implements SPIService{ 
  2.     public void execute() { 
  3.         System.out.println("SpiImpl1.execute()"); 
  4.     } 
  5.  
  6. public class SpiImpl2 implements SPIService{ 
  7.     public void execute() { 
  8.         System.out.println("SpiImpl2.execute()"); 
  9.     } 

最后呢,要在ClassPath路径下配置添加一个文件。文件名字是接口的全限定类名,内容是实现类的全限定类名,多个实现类用换行符分隔。内容就是实现类的全限定类名:

  1. com.tech.dayu.spi.SpiImpl1 
  2. com.tech.dayu.spi.SpiImpl2 

测试

  1. public class Test { 
  2.     public static void main(String[] args) {     
  3.         Iterator providers = Service.providers(SPIService.class); 
  4.         ServiceLoader load = ServiceLoader.load(SPIService.class); 
  5.  
  6.         while(providers.hasNext()) { 
  7.             SPIService ser = providers.next(); 
  8.             ser.execute(); 
  9.         } 
  10.         System.out.println("###################"); 
  11.         Iterator iterator = load.iterator(); 
  12.         while(iterator.hasNext()) { 
  13.             SPIService ser = iterator.next(); 
  14.             ser.execute(); 
  15.         } 
  16.     } 

两种方式的输出结果是一致的:

  1. SpiImpl1.execute() 
  2. SpiImpl2.execute() 
  3. -------------------------------- 
  4. SpiImpl1.execute() 
  5. SpiImpl2.execute() 

我们来看下源码,位于java.util包下。我们就以ServiceLoader.load为例,通过源码看看它里面到底怎么做的。

ServiceLoader.load()其实就是 Java SPI 入口

看到最后调用的是reload,最后生效的是在这个LazyIterator的内部,等同于是一个迭代器的遍历,遍历相应的文件中的service的实现类,就是我们上面命名的那些。

这里无论是if还是else最后调用的都是nextService()方法,点进去看

可以看到无非就是通过名字获取到文件路径,获取全限定名来加载类,并且创建其实例放入到相应的缓存之后并且返回实例,这大体就是整个的实现逻辑,应该不难吧,咱们自己来实现个这个应该也是分分钟的事

好了,Java的SPI源码分析的差不多了,问题也随之而来,比如不能按照需要加载,会一次性加载所有可用的扩展点,很多是不需要的,会浪费系统资源;不支持AOP和依赖注入,实现类的方式也不够灵活,只能通过 Iterator 形式获取

接下来咱们来分析Dubbo的SPI

Dubbo中的SPI

Dubbo 并未使用 Java SPI,而是重新实现了一套功能更强的 SPI 机制。

Dubbo SPI 的相关逻辑被封装在了 ExtensionLoader 类中,通过 ExtensionLoader,我们可以加载指定的实现类。Dubbo SPI 所需的配置文件需放置在 META-INF/dubbo 路径下。

Dubbo要判断一下,在系统运行时,应该选用这个Protocol接口的哪个实现类。它会去找一个你配置的Protocol,将你配置的Protocol实现类,加载进JVM,将其实例化,微内核,可插拔,大量的组件,Protocol负责RPC调用的东西,你可以实现自己的RPC调用组件,实现Protocol接口,给自己的一个实现类就可以啦

Dubbo里很多都是保留一个接口和多个实现,然后在系统运行的时候动态根据配置去找到对应的实现类。如果你没配置,那就走默认的实现就可以啦

我们随便来看一下其中的

并且 Dubbo SPI 除了可以按需加载实现类之外,增加了 IOC 和 AOP 的特性,还有个自适应扩展机制。

我们先来看一下 Dubbo 对配置文件目录的约定,不同于 Java SPI ,Dubbo 分为了三类目录。

接下来我们来看Dubbo的SPI的源码

在Dubbo中ExtensionLoader类似 Java SPI 中 ServiceLoader 的存在。大致流程就是先通过接口类找到ExtensionLoader ,然后再通过 ExtensionLoader.getExtension(name) 得到指定名字的实现类实例。

其实也是很简单的,就是通过一顿判断然后在缓存中检查是否存在这个类型的ExtensionLoader ,没有的话就新建一个放进去缓存,最后返回接口类的对应的ExtensionLoader

getExtension() 方法,从现象我们可以知道这个方法就是从类对应的 ExtensionLoader 中通过名字找到实例化完的实现类

内部的createExtension()方法,我就不截图了,比较长,就是先找实现类,判断是否有该类的缓存,没有的话就通过反射新建一个实例对象,然后放进去

到这里其实就差不多了分析的,拿到实例对然后就可以执行了

Dubbo的SPI主要就是为了增加框架的可拓展性,可以在其基础上进行二次开发,还有一个更重要的点就是不会像Java的SPI一样直接全部加载,那样可能会造成大量的资源浪费的,甚至可能还会做无用功

【编辑推荐】

  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区
  2. 照抄不翻车:抗住千万流量的大型分布式系统架构设计
  3. 2021年五大开源式游戏化工具
  4. 数字化转型的七大热门趋势和三大渐冷趋势
  5. Windows 11新预览版22449推送:启动引导动画变样了
  6. 什么情况?游戏玩家大规模退回Windows 7系统:Windows 10暴跌

 

来源:大鱼仙人内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯