什么';这是';使用';Java9中的指令?

什么';这是';使用';Java9中的指令?,java,java-9,java-module,module-info,Java,Java 9,Java Module,Module Info,Java的ServiceLoader类现在正式烘焙到Java语言中。您现在可以使用 provides <spiClass> with <providerClass> 引用 模块系统 可以识别 浏览 模块中的类文件 用于调用的工件 的 ServiceLoader::load 方法,但那会 慢条斯理 不可靠的。那是 模块使用特定的 服务是根本 该模块的 定义,两者都是 效率和清晰度我们 请用英文表达 模块的声明 使用uses子句: module java.sql {

Java的
ServiceLoader
类现在正式烘焙到Java语言中。您现在可以使用

provides <spiClass> with <providerClass>
引用

模块系统 可以识别 浏览 模块中的类文件 用于调用的工件 的
ServiceLoader::load
方法,但那会 慢条斯理 不可靠的。那是 模块使用特定的 服务是根本 该模块的 定义,两者都是 效率和清晰度我们 请用英文表达 模块的声明 使用uses子句:

module java.sql { requires transitive java.logging; requires transitive java.xml; exports java.sql; exports javax.sql; exports javax.transaction.xa; uses java.sql.Driver; } 模块java.sql{ 需要可传递的java.logging; 需要可传递的java.xml; 导出java.sql; 导出javax.sql; 导出javax.transaction.xa; 使用java.sql.Driver; }
为什么模块系统必须了解特定服务的用途,尤其是如何提高效率?服务不是惰性加载的吗?为什么服务加载器不能动态地查找提供者

引用Java 9 javadoc of(我添加了重点):

应用程序通过调用ServiceLoader的一个静态
load
方法来获取给定服务的服务加载器。如果应用程序是模块,则其模块声明必须具有指定服务的uses指令这有助于定位提供程序并确保其可靠执行。此外,如果服务不在应用程序模块中,则模块声明必须具有requires指令,该指令指定导出服务的模块

为什么模块系统必须了解特定服务的用途

因为依赖解析。在示例中,引用文本上方的几行表示:

为了让
java.sql
模块使用此驱动程序,
ServiceLoader
类必须能够通过反射实例化驱动程序类;为此,模块系统必须将驱动程序模块添加到模块图中,并解决其依赖关系

关键的一点是,反射被用来进行实例化。它发生在模块解析之后。。。在应用程序开始运行之后

。。。特别是这将如何提高效率

扫描代码库以查找对
ServiceLoader::load
的所有调用非常昂贵。仅仅知道调用了一个方法是不够的(这可以通过分析类文件依赖关系来完成)。您还需要知道使用了哪些参数来确定要加载哪些类。以及(正如SotMS文件所指出的)可能出现错误的情况;e、 g.如果参数是运行时表达式而不是编译时常量表达式


他们采用的解决方案是提供一种方法来显式声明对反射加载类的依赖关系。

当JVM启动时,模块系统将启动并构建模块图。在运行时,只有进入图形的模块才可用(即使其他模块可以观察到)。如果模块通过服务正确地解耦,那么提供模块的模块很有可能不是初始模块的可传递依赖项。因此,如果没有进一步的努力,服务提供者模块通常不会进入模块图,因此当模块尝试使用服务时,在运行时不可用

为了使
java.sql
模块使用此驱动程序[…],模块系统必须将驱动程序模块添加到模块图中并解决其依赖关系[…]

因此,为了使服务正常工作,提供者模块必须将其放入模块图中,即使它们不是从初始模块传递过来的。但是,模块系统如何识别哪些模块是服务提供商所需要的呢?所有使用
提供
子句的人?那就太过分了。不,应该只解决实际需要的服务提供商

这就需要确定服务的用途。正如其他人所指出的,字节码分析速度慢且不可靠,因此需要更明确的机制来保证效率和正确性:
使用
子句。只有使用它们,模块系统才能可靠、高效地提供所有服务提供商模块

如果应用程序是模块,则其模块声明必须具有指定服务的
uses
指令;这有助于定位提供程序并确保它们可靠地执行

如果使用标志“显示模块分辨率”启动,则可以观察此行为:

root monitor
monitor requires monitor.observer
[...]
monitor binds monitor.observer.beta
monitor binds monitor.observer.alpha
模块监视器绑定模块
monitor.observer.alpha
monitor.observer.beta
,即使它不依赖于这两个模块


(引用自;强调我的。)

“为了效率和清晰度”我不知道你在说什么。请澄清您的问题。好的,“开放”是关于一个模块使零件可用。但是“使用”是关于一个模块说它需要一些东西。这就像“请求”和“提供”之间的区别。我确实了解你的问题。问题是你没有得到我的答案。
提供了
语句,它不需要任何解析,而且绝大多数情况下不使用运行时反射。。。就像调用
Class::forName
ServiceLoader::load
一样。使用
Class::forName
加载模块中未通过其他方法解析的类将失败。因为类不会在那里加载。如果在编译时或模块加载时不知道类的名称,那么就不能依靠模块解析来解析依赖关系。您将需要以传统的方式处理依赖关系。。。通过e
root monitor
monitor requires monitor.observer
[...]
monitor binds monitor.observer.beta
monitor binds monitor.observer.alpha