SPI机制详解!

SPI 全称为 Service Provider Interface,是一种服务发现机制。

它通过在ClassPath路径下的META-INF/services文件夹查找文件,自动加载文件里所定义的类。

这一机制为很多框架扩展提供了可能,比如在Dubbo、JDBC中都使用到了SPI机制。

具体使用

定义一个接口,SPIService

1
2
3
public interface SPIService {
void execute();
}

定义两个实现类

1
2
3
4
5
6
7
8
9
10
11
public class SpiImpl1 implements SPIService{
public void execute() {
System.out.println("SpiImpl1.execute()");
}
}

public class SpiImpl2 implements SPIService{
public void execute() {
System.out.println("SpiImpl2.execute()");
}
}

在ClassPath路径下配置添加一个文件。

文件名字是接口的全限定类名,内容是实现类的全限定类名,多个实现类用换行符分隔。

1
2
com.viewscenes.netsupervisor.spi.SpiImpl1
com.viewscenes.netsupervisor.spi.SpiImpl2

通过ServiceLoader.load或者Service.providers方法拿到实现类的实例。

其中,Service.providers包位于sun.misc.Service,而ServiceLoader.load包位于java.util.ServiceLoader

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Test {
public static void main(String[] args) {
Iterator<SPIService> providers = Service.providers(SPIService.class);
ServiceLoader<SPIService> load = ServiceLoader.load(SPIService.class);

while(providers.hasNext()) {
SPIService ser = providers.next();
ser.execute();
}
System.out.println("--------------------------------");
Iterator<SPIService> iterator = load.iterator();
while(iterator.hasNext()) {
SPIService ser = iterator.next();
ser.execute();
}
}
}

基本原理:通过反射的方式,创建实现类的实例并返回。