1. wiki
SPI(Service Provider Interface)
,是一种服务发现机制。它通过在 ClassPath 路径下的 META-INF/services
文件夹查找文件,自动加载文件里所定义的类。
2. 用例
定义一个接口,用来被引用
1
2
3
4package com.spiDemo.spi;
public interface SPIService {
void execute();
}创建两个实现类
1
2
3
4
5
6
7package com.spiDemo;
public class SpiImpl1 implements SPIService {
public void execute() {
System.out.println("SpiImpl1.execute()");
}
}
1 | package com.spiDemo; |
在 ClassPath 路径下配置添加一个文件,文件名是接口的全限定类名,内容是实现类的全限定类名,多个实现类用换行符分隔
1
2
3
4
5
6# 位置
src/main/resources/META-INF/com.spiDemo.SPIService
# 内容
com.spiDemo.SpiImpl1
com.spiDemo.SpiImpl2调用可以通过
ServiceLoader.load()
或者Service.providers()
方法拿到实现类的实例1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38package com.spiDemo;
import java.util.Iterator;
import java.util.ServiceLoader;
import sun.misc.Service;
public class DBDriverDemo {
public static void main(String[] args) {
System.out.println("--------------------------------");
// 方法一
Iterator<SPIService> providers = Service.providers(SPIService.class);
while (providers.hasNext()) {
SPIService ser = providers.next();
ser.execute();
}
// 方法二
// ServiceLoader<SPIService> serviceLoader = ServiceLoader.load(SPIService.class);
// for (SPIService sPIService : serviceLoader){
// ...
// }
System.out.println("--------------------------------");
ServiceLoader<SPIService> load = ServiceLoader.load(SPIService.class);
Iterator<SPIService> iterator = load.iterator();
while (iterator.hasNext()) {
SPIService ser = iterator.next();
ser.execute();
}
}
}
# 输出
--------------------------------
SpiImpl1.execute()
SpiImpl2.execute()
--------------------------------
SpiImpl1.execute()
SpiImpl2.execute()
3. 注意
- 严格按照约定的文件路径和文件名来命名,”META-INF/services/“