0%

Java SPI

本文主要解析一下有关于Java的SPI技术。

ServiceLoader继承了Iterable,所以,在基本的使用时可以将它理解为一个迭代器,现在,
要关注的是ServiceLoader是如何加载类并实例化的。

ServiceLoader内部依然是通过ClassLoader#getResources()查询实现了接口的类全限定路径。

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
38

private Class<?> nextProviderClass() {
if (configs == null) {
try {
// 注意这里的PREFIX被限定为META-INF/services
String fullName = PREFIX + service.getName();
if (loader == null) {
configs = ClassLoader.getSystemResources(fullName);
} else if (loader == ClassLoaders.platformClassLoader()) {
// The platform classloader doesn't have a class path,
// but the boot loader might.
if (BootLoader.hasClassPath()) {
configs = BootLoader.findResources(fullName);
} else {
configs = Collections.emptyEnumeration();
}
} else {
configs = loader.getResources(fullName);
}
} catch (IOException x) {
fail(service, "Error locating configuration files", x);
}
}
while ((pending == null) || !pending.hasNext()) {
if (!configs.hasMoreElements()) {
return null;
}
pending = parse(configs.nextElement());
}
String cn = pending.next();
try {
return Class.forName(cn, false, loader);
} catch (ClassNotFoundException x) {
fail(service, "Provider " + cn + " not found");
return null;
}
}

META-INF/services