本文主要解析一下有关于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