听说过api,但是你听说过spi吗

在空闲的时间中,总是喜欢去看看技术类的博客,无意间看到spi这个玩意儿,作为一个有追求的程序员,对于每一个点都会去查查看,看看这个点是否能帮助自己的应用构建的更加优雅、健壮和稳定。果然spi没有让我失望,下面介绍一下spi机制。

一、浅谈api和spi的区别:

在OOP编程的过程中,为了降低系统的耦合性,模块之间和模块之间总是使用接口的方式进行通信。

1.1、场景:

例如在我们的系统当中,针对于搜索业务有很多的实现方案,①:基于xml文件进行搜索,②:基于数据库进行搜索,③:基于文件检索。但是我们在使用接口的时候必须要在代码中指定一种实现来完成搜索功能。

1.2、问题:

请思考一种情况,现在搜索业务需要第三方来实现,我们尚且都不知道第三方是如何实现的,那么我们又如何指定实现类呢。

1.3、既然有问题,解决方案肯定会是有的:

我们要抓住问题的根源,上述问题中主要是:不能在程序中动态的指明接口的实现,缺乏服务的发现机制。java的spi即提供了这样的一中机制:为某个接口寻找服务实现的机制,其思想类似ioc,就是将程序的控制权转译服务实现方,在模块话的程序设计中,这个是非常的重要的。

总结一下:利用api可以实现模块间的解耦,提高系统的灵活性。但是假若要对系统的模块进行扩展的时候,spi就会排上用场了。

二、目前spi的应用,看看这么牛逼的机制到底有谁在为其背书:

  • dubbo中利用spi进行了扩展
  • springboot的自动装配机制(spi的变形,文件给出的是spring.factories,这个机制目前我也没有详细的研究)
  • jdbc 其实现都是交由各个厂商来实现的

三、呈上代码,进一步的了解:

  • ISearchSPI.java 类
package spi;
public interface ISearchSPI {
    /**
     * 依据关键字 keyWork来查找用户信息
     * @param keyWork
     * @return
     */
    String search(String keyWork);
}
  • FileSearchImpl.java
package spi;
public class FileSearchImpl implements ISearchSPI{
    @Override
    public String search(String keyWork) {
        return "朕是文本搜索";
    }
}
  • SpiderSearchImpl.java
package spi;
public class SpiderSearchImpl implements ISearchSPI{
    @Override
    public String search(String keyWork) {
        return "臣妾来自网络爬虫 搜索!!!";
    }
}
  • SPITest.java 测试类:
package spi;

import java.util.Iterator;
import java.util.ServiceLoader;

public class SPITest {

    public static void main(String[] args) {

        ServiceLoader<ISearchSPI> load = ServiceLoader.load(ISearchSPI.class);
        Iterator<ISearchSPI> iterator = load.iterator();
        while (iterator.hasNext()){
            ISearchSPI next = iterator.next();
            String spiTest = next.search("测试spi");
            System.out.println(spiTest);
        }
    }
}
  • spi实现的核心
在resources目录下建立META-INF,在这个目录下建立services文件夹,最后建spiISearchspi文件(不要然和后缀),把实现spi的类的全路径名称写出来
spi.FileSearchImpl
spi.SpiderSearchImpl

image.png

  • 测试结果:
    image.png
    看到上面的代码是不是很有一种很清爽的感觉,实际的实现部分完全是可插拔的,作为接口完全不用指名实现类调用,仅仅用下面的一行代码即可搞定。这样的方式会大大的提高你的程序的可扩展性
ServiceLoader<ISearchSPI> load = ServiceLoader.load(ISearchSPI.class);

四、关于spi的思考:

学习到新的技能点,总是需要如何把它运用到以后的coding中,才能让这个知识点更加的有意义,但是也要防止过犹不及的炫技。

在以后我们除了api的解耦方式之外,还可以提过spi的机制。这对于我们在编程中不同的组不同的部门之间的程序的通信又有了一种新的机制。同时如果我们有机会进入基础架构组的话,自写框架的就有了一种新的扩展机制,可以通过spi机制来让我们的框架可接受更多的插件,做到完全可插拔的形式(目前dubbo就是这样干的)很容易形成一种生态(springboot现在不就是这样的吗),

用场景驱动的方式,讲述能投看的懂能落地的技术。加入java技术进阶交流群(570980002)一起纯粹的讨论技术(非培训机构)。

博客首发地址csdn:https://blog.csdn.net/weixin_42849915
简书地址:https://www.jianshu.com/u/4b48be4cf59f
希望结识更多的大牛一同学习一同进步

原文地址:https://www.cnblogs.com/fkxuexi/p/10674043.html