SPI的全称是Service Provider Interface服务提供接口,是JDK内置的一种 服务提供发现机制,例如我们常用的数据库驱动Driver,就是基于SPI来做的。
运行机制:
服务的调用方需要调用服务提供方的服务,如果在调用方中直接来调用服务提供方,会导致耦合性较高,不利于扩展
- 因此,就出现了SPI,在SPI中,有一套标准的服务接口,调用方只需要面向接口来调用,并不需要关心服务是谁实现的、谁提供的。
- 服务的提供方需要提供这一套标准接口的实现类,也就是服务的具体实现,并将自己的服务实现暴露出去
- 怎么暴露呢?SPI规定了,服务的提供方,需要在自己的
classpath/META-INF/services
目录下,创建一个配置文件,这个文件以标准服务接口的全路径名为文件名,文件中的内容就是实现类的全路径名 - 那么在JDK中如何发现服务呢?JDK在启动时会自动扫描
classpath/META-INF/services
中的实现类,并加载这个服务实现类,这样就完成了服务的发现机制
这样,服务调用方、提供方实现了解耦,更加利于维护和扩展。
以JDBC为例,
- JDBC提供了标准服务接口,也就是Driver接口,服务的提供方,也就是不同的数据库厂商,需要提供Driver接口的实现类。
- 当我们导入了mysql的驱动依赖,也就是服务的提供方,JDK会自动扫描所有依赖中
classpath/META-INF/services
下的配置文件,加载这个实现类,这样就完成了服务的发现。JDK中完成服务发现的类是java.util.ServiceLoader
- 我们的程序,也就是服务的调用方,只需要面向标准接口来编程,而不需要关心服务的具体实现。同时我们可以任意更换不同的数据库驱动,而不需要改动原有的代码。
来看一下mysql驱动依赖
会看到在mysql驱动依赖的classpath/META-INF/services
下存在一个配置文件,这个配置文件以服务接口的全路径名为文件名
打开这个文件,文件中的内容就是服务实现类的全路径名
这就是SPI机制。
SpringBoot中的自动配置也是效仿SPI机制来做的。