dubbo 的 spi 思想是什么?
**

面试题**
dubbo 的 spi 思想是什么?
面试官心理分析
继续深入探讨吧!前面已经了解了一些基础知识,请确认你没问题吗?熟悉dubbo的一些基本概念后,请进一步探讨一个稍微复杂的问题吧!
问题一:什么是SPI?
问题二:dubbo中的SPI是如何实现的?
其实就是看看你对 dubbo 的掌握如何。
面试题剖析
spi 是啥?
SPI是什么?简单来说就是service provider interface。到底是什么意思呢?举个例子来说吧。假设你有一个接口,在实际运行中如何选择合适的实现了?这就需要用到 SPI 来完成。具体取决于设置中的参数设置或者按照默认设置来处理。 SPI 的主要功能是帮助确定在多个可能的实现场口中选择一个合适的实现了。具体来说,在系统初始化时会先根据参数查找匹配到的具体实现场所并将其加载到系统中;随后就可以使用该实例对象来进行后续的操作和管理。
举个栗子。
你有一个API A。A1、A2、A3分别代表该API的不同具体实现方案。通过设置接口 A = 实现 A2的方式进行配置,在实际运行过程中系统将按照该配置选择并创建相应的对象实例来提供服务功能。
在哪些应用场景中通常会采用SPI机制?比如你创建了一个供他人使用的开源框架,在这种情况下如果希望他人能够自行编写插件并将其整合到你的开源框架中,则需要用到SPI思想来实现功能扩展。
Java spi 思想的体现
spi 经典的思想体现,大家平时都在用,比如说 jdbc。
Java 定义了一套 jdbc 的接口,但是 Java 并没有提供 jdbc 的实现类。
但是实际上在项目运行时为了使用JDBC接口需要了解哪些具体的实现类呢?通常情况下我们需要根据实际使用的数据库系统来选择合适的 JDBC连接器包。例如MySQL数据库则需要导入mysql-jdbc-connector.jar这个JAR文件到项目的JDK类库目录中;如果是Oracle数据库则需要导入相应的 JDBC连接器包。
当系统运行时,在调用jdbc接口时(或:遇到)会发现底层机制(或:底层结构)采用了 jar中包含的那些实现类。
dubbo 的 spi 思想
dubbo 也采用了 spi 思想,但是未使用 jdk 的 spi 机制,自行开发了一整套 spi 机制.
Protocol protocol =ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();Copy to clipboardErrorCopied
代码解读
协议接口,在系统运行时,Dubbo会根据某种机制来选择相应的实现类来创建对象。
该工具将试图获取指定的协议实例,并尝试加载预定义好的协议实现类到当前虚拟机环境中。随后会生成相应的对象实例。这样就可以直接使用你的协议实现类进行操作了。
在Dubbo框架中存在大量使用这一模式的代码实例。具体来说,在每个组件都设计了一个统一的接口并提供了多种功能实现的情况下,在运行时会通过动态加载机制匹配到相应的功能模块。值得注意的是,在这种模式下,默认情况下会优先考虑具体的配置信息来确定如何处理请求;如果未指定特定功能,则会默认采用基础功能模块来完成请求处理工作
@SPI("dubbo")publicinterfaceProtocol{intgetDefaultPort();@Adaptive<T>Exporter<T>export(Invoker<T> invoker)throwsRpcException;@Adaptive<T>Invoker<T>refer(Class<T> type,URL url)throwsRpcException;voiddestroy();}Copy to clipboardErrorCopied
代码解读
在 dubbo 项目的 JAR 包中,并存在于该目录下的 /META_INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol 文件中:
dubbo=com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol
http=com.alibaba.dubbo.rpc.protocol.http.HttpProtocol
hessian=com.alibaba.dubbo.rpc.protocol.hessian.HessianProtocolCopy to clipboardErrorCopied
代码解读
所以这表明dubbo的spi机制默认运作的方式是什么。这本质上是协议接口。具体来说@SPI("dubbo")的意思是说通过spi机制来配置实现类。具体来说就是通过spi机制来提供基于dubbo的技术实现。而实现类则是在配置文件中通过dubbo作为默认键查找得到的。需要注意的是配置文件名与接口全限定名一致。这样做的目的是为了方便快速定位到对应的具体实现类名称即在配置文件中找到与当前协议完全匹配的名字就可以直接获取到该接口下的默认实现类了。例如对于一个名为com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol的协议接口其对应的默认实现类就是com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol这个类型
如果需要动态替换默认的实现类,则可以通过 @Adaptive 接口来实现;在 Protocol 接口中定义了两个方法,并都标注了 @Adaptive ,这些接口将被代理来完成功能。
啥意思呢?
该协议接口增加了两个@Adaptive注解标注的方法,在运行时会针对Protocol自动生成代理类;该代理类中的两个方法中包含有代理代码;这些代码会根据Url中的protocol动态获取对应的键值,默认情况下使用dubbo机制;但您也可以自行设置不同的键值来获取相应的实现类实例。
如何自己扩展 dubbo 中的组件
下面来说说怎么来自己扩展 dubbo 中的组件。
我可以创建一个能够打包成JAR包的工程,在项目根目录下的src/main/resources目录中创建一个名为META-INF/services的应用服务目录,并在此目录中放入名为com.alibaba.dubbo.rpc.Protocol.java的Java类文件。在 META-INF/services 目录下添加一条配置记录:my=com.bingo.MyProtocol。将该工程发布至nexus服务网关供其他应用使用
然后,在项目中构建一个Dubbo Provider服务,并在此过程中引用自定义开发的JAR包;接着,在Spring管理器类的配置文件中新增相应的服务绑定设置,并指定相关的键值对以实现与该组件的集成。
<dubbo:protocolname=”my”port=”20000”/>Copy to clipboardErrorCopied
代码解读
当一个provider启动时,它会将注册到我们jar包中的my=com.bingo.MyProtocol配置注入其中。随后,在你的配置文件中就可以直接使用这个自定义协议了。这种方法实际上就是替代Dubbo内部提供的组件,并通过简单的配置实现扩展性功能。

dubbo 提供了丰富的扩展方案, 即如果你想要扩展某个功能, 只需创建一个jar包, 并让目标工程依赖这个jar包, 在该jar包指定目录下配置好对应接口名称及其映射文件, 其中通过key=实现类属性进行配置。
然后对于对应的组件来说,类似于 <dubbo:protocol> 的做法是采用对应于该组件的一个特定键值对所定义的实现类来完成某个接口的功能,并提供你自己的一些具体实现方案以供扩展使用
订阅「小新杂谈社 」公众号后,请您在收到消息后回复 AI ,即可下载或领取丰富的学习资源、创业指南以及一些实用的AI工具和丰富的学习材料!


