我是靠谱客的博主 怡然蜡烛,最近开发中收集的这篇文章主要介绍Dubbo的SPI思想SPI 是啥?SPI有啥用?Java SPI 思想的体现Java 的 SPI 实现机制Dubbo 的 SPI 思想如何自己扩展 dubbo 中的组件,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

SPI 是啥?

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

举个栗子。

你有一个接口 AA1/A2/A3 分别是接口A的不同实现。你通过配置 接口 A = 实现 A2,那么在系统实际运行的时候,会加载你的配置,用实现 A2 实例化一个对象来提供服务。

spi 机制一般用在哪儿?插件扩展的场景,比如说你开发了一个给别人使用的开源框架,如果你想让别人自己写个插件,插到你的开源框架里面,从而扩展某个功能,这个时候 spi 思想就用上了。

SPI有啥用?

“接口定义者”只有一些接口定义,然后还有一些基于该些接口的编程代码,“服务实现者”需要根据这些接口规范去开发自己的实现,然后“服务实现者”会作为依赖注入到“接口定义者”所在项目,实现无代码侵入,一条配置即可切换“服务实现者”。 核心思想就是模块与模块之间基于接口编程,没有直接耦合,随意插拔,随意切换,随意扩展。

Java SPI 思想的体现

spi 经典的思想体现,大家平时都在用,比如说 jdbc

Java 定义了一套 jdbc 的接口,但是 Java 并没有提供 jdbc 的实现类。

但是实际上项目跑的时候,要使用 jdbc 接口的哪些实现类呢?一般来说,我们要根据自己使用的数据库,比如 mysql,你就将 mysql-jdbc-connector.jar 引入进来;oracle,你就将 oracle-jdbc-connector.jar 引入进来。

在系统跑的时候,碰到你使用 jdbc 的接口,他会在底层使用你引入的那个 jar 中提供的实现类。

Java 的 SPI 实现机制

主要是接口定义者和服务实现者之间指定了一些规范,并根据这些规范,当服务提供者模块插入接口定义者所在模块时,实现服务提供者模块内的对应的类的自动加载、链接、初始化。这就是SPI做的全部。

1、如何规范的:

Java里面的SPI的具体的规范是:服务提供者需要在META-INF/services/目录下以接口全名称作为文件名,文件里面写上具体的实现类名称。

以com.sql.Driver为例进行说明:

当我们系统中引入mysql-connector-java时,可以在对应的META-INF/services/目录下发现:

 发现一个以java.sql.Driver类全限定名命名的文件,里面写了具体的实现类:com.mysql.jdbc.Driver:

 2、如何对指定的类进行自动加载、链接、初始化的:

参考一个demo: Java SPI详解 - jy的blog - 博客园    通过这个demo演示了SPI的工作方式,其核心就是JDK自带的ServiceLoader.load(), 以及LazyIterator.hasNextService(), LazyIterator.nextService(), 其中所做的事情就是按照接口全名称去所有的META-INF/services/目录下找到对应的文件,然后提取所有的实现类全名称,然后进行Class.forName(“实现类全名称”),进行实现类的加载、链接、初始化,然后就可以使用这个类了。

Dubbo SPI 思想

dubbo 也用了 spi 思想,不过没有用 jdk spi 机制,是自己实现的一套 spi 机制。

以Protocol来举例说明:

@SPI("dubbo")  
public interface Protocol {  
          
    int getDefaultPort();      
  
    @Adaptive      
    <T> Exporter<T> export(Invoker<T> invoker) throws RpcException;   
     
    @Adaptive      
    <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;      

    void destroy();    
}  
Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();

Protocol 接口,在系统运行的时候动态根据配置去找到对应的实现类。如果你没配置,那就走默认的实现。

<dubbo:protocol name=”my” port=”20000” />

它会去找一个你配置的 Protocol,将你配置的 Protocol 实现类,加载到 jvm 中来,然后实例化对象,就用你的那个 Protocol 实现类就可以了。这这里就是根据"my"这个关键字去找到对应的Protocol的实现类。

dubbo 自己的 jar 里,在/META_INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol文件中(其中com.alibaba.dubbo.rpc.Protocol为Protocol类的全限定名):

my=com.bingo.MyProtocol
dubbo=com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol
http=com.alibaba.dubbo.rpc.protocol.http.HttpProtocol
hessian=com.alibaba.dubbo.rpc.protocol.hessian.HessianProtocol

根据关键字“my”我们找到实现类:com.bingo.MyProtocol

当然,如果你没有配置<dubbo:protocol/>,那么默认的就会使用Protocol接口定义头上的@SPI("dubbo") ,默认以“dubbo”为关键字去查找实现类。

如何自己扩展 dubbo 中的组件

下面来说说怎么来自己扩展 dubbo 中的组件。

1自己写个工程,要是那种可以打成 jar 包的,写一个com.bingo.MyProtocol类,实现Protocol

2里面的 src/main/resources 目录下,搞一个 META-INF/services,里面放个文件叫:com.alibaba.dubbo.rpc.Protocol,文件里写上my=com.bingo.MyProtocol

3然后自己搞一个 dubbo provider 工程,在这个工程里面依赖你自己搞的那个 jar,然后在 spring 配置文件里给个配置:

<dubbo:protocol name=”my” port=”20000” />

provider 启动的时候,就会加载到我们 jar 包里的my=com.bingo.MyProtocol 这行配置里,接着会根据你的配置使用你定义好的 MyProtocol 了。

通过上述方式,可以替换掉大量的 dubbo 内部的组件。

最后

以上就是怡然蜡烛为你收集整理的Dubbo的SPI思想SPI 是啥?SPI有啥用?Java SPI 思想的体现Java 的 SPI 实现机制Dubbo 的 SPI 思想如何自己扩展 dubbo 中的组件的全部内容,希望文章能够帮你解决Dubbo的SPI思想SPI 是啥?SPI有啥用?Java SPI 思想的体现Java 的 SPI 实现机制Dubbo 的 SPI 思想如何自己扩展 dubbo 中的组件所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部