Java SPI 是怎么发现实现类的?这篇用 classpath 与模块两种方式各做一遍,把惰性实例化、缓存、出错时机和模块声明逐项验证(已有的 ServiceLoader 相关文章在模块化一类里)。
ServiceLoader.load(...) 返回后,还没有迭代:没有任何构造器运行(惰性)
先只看 providers 的类型(sl.stream().map(Provider::type)):[B, A, C]——仍然没有实例化
第一次迭代(for-each):
[B 的构造器运行]
得到 B
[A 的构造器运行]
得到 A
[C 的构造器运行]
得到 C
第二次迭代(缓存):
没有再运行构造器,顺序 = [B, A, C]
reload() 之后再迭代:
[B 的构造器运行]
得到 B
[A 的构造器运行]
得到 A
[C 的构造器运行]
得到 C
[B 的构造器运行]
findFirst() 只实例化第一个:
得到 B [不存在的类 Nope]
[B 的构造器运行]
B
迭代时抛 ServiceConfigurationError: Provider Nope not found
[存在但没有实现 Greeter 的类 Plain]
[B 的构造器运行]
B
迭代时抛 ServiceConfigurationError: Plain not a subtype
[只有带参构造器的类 NoDefault]
[B 的构造器运行]
B
迭代时抛 ServiceConfigurationError: NoDefault Unable to get public no-arg constructor [module-path 里有 api、impl、app]
Hello(来自模块 impl)
Hi(来自模块 impl)
[module-path 里只有 api、app(没有 impl)]
(没有输出:找不到任何实现)
java --describe-module impl:
impl file://<jtmp>/j20m/mods/impl/
requires api
requires java.base mandated
provides spi.Greeter with impl.Hello impl.Hi
contains impl