首先,SPI
是jdk制定的一种规范 ,满足服务使用者在符合开闭原则
基础上来编写代码,而能能够实现使用不同的服务提供方提供的服务,既然是规范肯定就需要有接口,而后还要有接口的具体实现,以及具体实现如何暴露给使用者,最后使用者如何使用这些具体实现,都会在SPI
中进行制定。如数据库驱动,日志等,有些抽象,接下里使用一个实例来进行说明其具体的使用方法。
本例子会采用maven父子项目方式创建5
个项目(模块),分别如下:
1:spiparent,作为父项目。
2:spiinterface,指定spi规范的接口,简单定义一个sayHi的方法。
3:spiconcrete-english,实现spiinterface中的接口,实现方式为使用英语sayHi。
4:spiconcrete-chinese,实现spiinterface的接口,实现方式为使用汉语sayHi。
5:spi-invoker,spiconcrete-english和spiconcrete-chinese的具体使用者。
spiparent
maven
,不勾选Create from archetype
GAV
信息Artifactid
保持一致,因此可不做修改。pom.xml
,不需要源代码文件和资源文件等,因此直接删除src
。spiinterface
spiconcrete-english
同2.2
,只不过ArtifactId=spiconcrete-english
,设置完如下:
spiconcrete-chinese
同2.2
,只不过ArtifactId=spiconcrete-chinese
,设置完如下:
spi-invoker
同2.2
,只不过ArtifactId=spi-invoker
,设置完如下:
spiinterface
定义接口public interface SayHi {
void sayHi();
}
spiconcrete-chinese
实现接口spiinterface
<dependencies>
<dependency>
<groupId>dongshi.daddygroupId>
<artifactId>spiinterfaceartifactId>
<version>1.0-SNAPSHOTversion>
dependency>
dependencies>
public class ChineseSayHi implements SayHi {
public void sayHi() {
System.out.println("你好,欢迎来到叶寨村!!!");
}
}
dongshi.daddy.ChineseSayHi
spiconcrete-english
实现接口spiinterface
<dependencies>
<dependency>
<groupId>dongshi.daddygroupId>
<artifactId>spiinterfaceartifactId>
<version>1.0-SNAPSHOTversion>
dependency>
dependencies>
public class EnglishSayHi implements SayHi {
public void sayHi() {
System.out.println("welcome to yezhaicun country!!!");
}
}
dongshi.daddy.EnglishSayHi
具体使用会用到SPI规范中提供的工具类java.util.ServiceLoader
,该工具类专门用来从classpath下的META-INF/services
下加载对应的具体服务的实现。
spi-invoker
编写测试类spiconcrete-chinese
) <dependencies>
<dependency>
<groupId>dongshi.daddygroupId>
<artifactId>spiinterfaceartifactId>
<version>1.0-SNAPSHOTversion>
dependency>
<dependency>
<groupId>dongshi.daddygroupId>
<artifactId>spiconcrete-chineseartifactId>
<version>1.0-SNAPSHOTversion>
dependency>
dependencies>
public class SayHiTestMain {
public static void main(String[] args) {
ServiceLoader<SayHi> load = ServiceLoader.load(SayHi.class);
for (SayHi sayHi : load) {
sayHi.sayHi();
}
}
}
你好,欢迎来到叶寨村!!!
如果此时我们想要使用英语来sayHi,怎么办呢?只需要将spiconcrete-chinese
换为spiconcrete-english
的依赖即可,如下:
<dependencies>
<dependency>
<groupId>dongshi.daddygroupId>
<artifactId>spiinterfaceartifactId>
<version>1.0-SNAPSHOTversion>
dependency>
<dependency>
<groupId>dongshi.daddygroupId>
<artifactId>spiconcrete-englishartifactId>
<version>1.0-SNAPSHOTversion>
dependency>
dependencies>
welcome to yezhaicun country!!!
满足了开闭原则
。
这里。
数据库在计算机领域具有非常重要的地位,因此对于数据相关的驱动则无疑是更加重要的,因为我们使用操作数据库必须依赖于这些驱动程序,因此驱动领域中的规范
就显的尤为的重要了,对于此,jdk大佬们基于SPI的规范定义了数据库驱动的规范接口,该接口是java.sql.Driver
,具体定义如下:
package java.sql;
public interface Driver {
}
接下来以mysql驱动程序为例进行说明。如下是MySQL数据库驱动包截图,可以看到里面定义了META-INF/services/java.sql.Driver
文件,内容为该类的具体实现类:
com.mysql.jdbc.Driver
com.mysql.jdbc.Driver
类定义如下:
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
public Driver() throws SQLException {
}
static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
}
可以看到其实现了数据库驱动SPI规范接口java.sql.Driver
。