SPI机制名称是“服务提供接口”,网上的解释其用途主要是用于解耦,通俗讲,它的作用就是寻找接口的实现类,wq可以认为是A调用B中的一个特殊的调用方式而已,也就是说一种特殊的服务发现机制。网上有句话说的很多,它解耦解的是让接口和实现类完全分离,谁想去实现它可以去实现,我业务层一样可以无感的使用这些实现类。 这个的特点就是面向接口编程,模块之间不对实现类进行硬编码。
SPI用到的设计模式是桥接模式。注意它和RPC没什么关系。
传送门:【JavaWeb】 Sping SPI机制详解_spring spi机制用于-优快云博客
那么怎么做到B的服务被A去发现的呢,我们先对其历史进行溯源:
一、JDK SPI机制
开始出现SPI机制是JDK,成为JDK SPI,也叫java SPI。
一句话概括就是 业务应用(比如TQH1)调用核心应用(CS1)的记账贷记方法(Account.daiji()),而贷记的实现可以有很多,比如一卡通的贷记,是基础部门做了实现CardAccount.daiji()、比如财富账户的贷记FiAccount.daiji(),是财富平台部门做了对应的实现。但我们的调用逻辑可以不用修改,直接用serviceload加载出所有的实现类,然后循环看哪个实现类是真正需要的,去调用.daiji方法就好。
使用场景:
java的jdbc规定一套统一的数据库规范协议,比如获取数据库连接,所以在jdk的java.sql目录里面写了这么一个接口:
public interface Driver {
void getConnection();
}
然后具体的实现交给各个第三方数据库厂商,比如mysql、oracle。以mysql的jar包为例,它会去实现java的这个方法:
public MysqlDriverImpl implement Driver {
@Overide
getConnection() {
//实现了这个方法
}
}
然后我的业务代码里面肯定要引入mysql的jar包,我要去获取数据库连接,可以直接new 一个MysqlDriverImpl类,然后用里面的方法就可以了。那如果我中间又换了数据库oracle了,岂不是又要改一遍核心代码?所以为了做到不关心这个,我们就用到了SPI机制,也就是java.util包里面提供了一个ServiceLoader的类加载的类,它可以根据SPI规范的配置,把所有实现了Driver的实现类都实例化出来,然后直接用实例的方法就好。也就是说我的业务应用只依赖mysql,那我的ServiceLoader只可以拿到mysql实现Driver的实例MysqlDriverImpl,如果同时还以来了oracle,那还可以拿到oracle的实现Dirver的实例:
//load方法会把实现了Driver接口的各个实现类全部实例化出对象来
//这也是jdk SPI的弱点,一定都会全部找出来,是个集合,无法只找某一个
ServiceLoader<Driver> services=ServiceLoader.load(Driver.class);
//构造迭代器
Iterator<Driver> iterator=service