在对问题进行概念验证时 - JPMS ServiceLoader does not work for me as expected .
我达到了一种状态,以了解在向模块路径提供 jar 与目标类时如何解决两个模块的差异。控制台有一个单行差异:
base.service binds user.service file://.../user-service/target/classes/
这实际上意味着什么?在 spec 中真的找不到该术语的此类引用。或 conceptual draft .此外,在自动模块解析期间,这种行为何时会有所不同? (引用 this answer)
最佳答案
这很可能是指 resolveAndBind
的绑定(bind)操作加工uses
— provides
关系。
This method works exactly as specified by
resolve
except that the graph of resolved modules is augmented with modules induced by the service-use dependence relation.More specifically, the root modules are resolved as if by calling
resolve
. The resolved modules, and all modules in the parent configurations, withservice dependences
are then examined. All modules found by the given module finders thatprovide
an implementation of one or more of the service types are added to the module graph and then resolved as if by calling theresolve
method. Adding modules to the module graph may introduce new service-use dependences and so the process works iteratively until no more modules are added.
因此,绑定(bind)发生在解析之后,但仍然在调用相关模块的任何代码之前。即,是否
ServiceLoader
无关紧要。是否在模块中实际使用。但是当它被使用时,它会利用已经可用的信息。因此,此时已经排除了许多潜在问题。这也是我们可以构建优化的模块图像预链接此类服务的原因。但是,这不适用于自动模块,因为它们没有
uses
指令。如果没有这些信息,服务查找只能在实际使用 ServiceLoader
时进行。会发生,就像通过旧类路径加载的类一样。请注意,链接问答中的问题有点不同。根据 OP 的信息,编译时使用了模块声明。但是,OP 使用
-jar
运行了应用程序。选项将指定的 jar 文件放在类路径上并从那里加载它,创建一个未命名的模块,而不是一个自动模块。这将忽略已编译的 module-info
而在没有老式的情况下META-INF/services/…
资源,根本没有找到服务实现。 OP 的代码被设计为在没有找到的情况下回退到默认服务实现,这与通过 ServiceLoader
查找默认服务的场景没有区别。 .您的答案的关键区别在于 start 方法
-m base.service/base.service.ServiceUser
,这将定位 base.service
通过模块路径并启动它的 base.service.ServiceUser
,以及 --add-modules …user.service
, 以确保提供服务的模块将被添加到运行时环境中。后者是必需的,因为没有直接依赖于启动的模块 base.service
到 user.service
,所以它不会自动加载。因此,在您的答案设置中,两个模块都按原样加载。当他们有
module-info
,其 provides
指令将被处理以查找服务实现,否则,它是一个自动模块,必须有 META-INF/services/…
文件。如上所述,没有等效于 uses
自动模块的指令,因此您永远不会看到它们的“绑定(bind)”日志条目。但他们可能仍会使用服务查找。
关于java - 在解析过程中,module.a 绑定(bind) module.b 是什么意思?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68693148/