gpt4 book ai didi

Java ServiceLoader 解释

转载 作者:搜寻专家 更新时间:2023-11-01 02:58:20 26 4
gpt4 key购买 nike

我想了解Java ServiceLoader的概念、工作机制和具体用例,但找到官方documentation过于抽象和困惑。

首先,文档概述了服务服务提供商。服务是一组封装在 jar 存档(API 库)中的接口(interface)和抽象类。服务提供者是一组实现或扩展 API 的类,打包在一个不同的 jar 文件(提供者库)中。


到目前为止一切顺利,但随后文档变得困惑。

For the purpose of loading, a service is represented by a single type, that is, a single interface or abstract class. (A concrete class can be used, but this is not recommended.) A provider of a given service contains one or more concrete classes that extend this service type with data and code specific to the provider. The provider class is typically not the entire provider itself but rather a proxy which contains enough information to decide whether the provider is able to satisfy a particular request together with code that can create the actual provider on demand. The details of provider classes tend to be highly service-specific; no single class or interface could possibly unify them, so no such type is defined here. The only requirement enforced by this facility is that provider classes must have a zero-argument constructor so that they can be instantiated during loading.

那么什么是服务类型提供商类?我的印象是,服务类型是 facade在API库中,provider类是这个facade接口(interface)在provider库中的实现,ServiceLoader实际加载的类。这样对吗?但对我来说,所有组件如何联系在一起仍然没有多大意义。

提供者类作为代理来决定提供者是否能够满足特定请求以及可以按需创建实际提供者的代码是什么意思?在哪里不能定义统一类型?基本上这一段都是令人困惑的,我想通过一个具体的例子来听听更容易理解的解释。


然后关于提供者配置文件...

A service provider is identified by placing a provider-configuration file in the resource directory META-INF/services. The file's name is the fully-qualified binary name of the service's type. The file contains a list of fully-qualified binary names of concrete provider classes, one per line ...

The configuration file naming a particular provider need not be in the same jar file or other distribution unit as the provider itself. The provider must be accessible from the same class loader that was initially queried to locate the configuration file; note that this is not necessarily the class loader from which the file was actually loaded.

这是否意味着对于服务类型为 org.foo.BarServiceType 的 API,在类路径中必须存在具有实现此类型的类的提供者 jar META-INF/services/org.foo.BarServiceType 命名的提供者配置文件列出了这个提供者类,所有这些都可以通过加载 ServiceLoader 的同一个 Classloader 访问,以在API?

从类加载器的角度来看,可访问意味着提供者配置文件和提供者库可以在包外部提供,位于层次结构的上层,即来自容器或其他中间件。

提供者配置文件列出了提供者类,并且可能捆绑在提供者包中(如果捆绑了为什么还要列出多个类?)或者来自外部。但哪种方法更常见:在提供者之间提供配置文件,还是提供列出 API 库本身中一组受支持提供者的文件?或者后者是一种误解?


最后关于ServiceLoader

ServiceLoader 实际实例化和调用加载服务提供者的地方?这是否发生在 API 库提供的工厂方法中?例如,SLF4JLoggingFactory.getLogger(clazz) 是否在内部委托(delegate)给 ServiceLoader,它使用反射来读取提供程序配置文件并加载服务?

服务加载机制如何处理以下情况:存在多个提供者及其配置文件,或者存在提供者配置文件条目但没有类本身?

ServiceLoader 在日志框架之外还有哪些其他具体用例?它在 Java EESpringHibernate 等流行框架中的使用率如何?使用松散耦合 API 的服务加载机制有哪些替代方案 - 提供者绑定(bind),或者是否存在?

最佳答案

服务类型是传递给 ServiceLoader.load 或 ServiceLoader.loadInstalled 的接口(interface)或抽象类。提供者是该接口(interface)或抽象类的具体实现。

由于服务通常包含大量功能,因此如果在 ServiceLoader 扫描它们时没有立即加载如此大的类,这将很有用。相反,更好的设计是提供对主要功能的访问的小类。例如,ServiceLoader.load(FileSystemProvider.class) 不会加载能够处理一组特定文件系统的整个库;相反,它加载一个 FileSystemProvider 对象,该对象能够初始化该库,当且仅当应用程序选择使用它时。这允许提供程序本身保持轻量级。

Does this mean for an API with service type of org.foo.BarServiceType, in the classpath there must exists the provider jar with a class implementing this type and META-INF/services/org.foo.BarServiceType named provider configuration file listing this provider class, all accessible by the same Classloader which loaded ServiceLoader to find and bind the provider on the API?

是的。通常这很简单;例如,包含 org.foo.BarServiceType 实现类的 .jar 文件还包含一个 META-INF/services/org.foo.BarServiceType 条目,其内容由一行文本组成。

why would it list multiple classes anyway if bundled?

有些服务提供商只能处理某些情况。一个例子是 IIORegistry类(它没有提到 ServiceLoader,实际上早在 ServiceLoader 被添加到 Java SE 之前就已经存在,但功能与 ServiceLoader 相同)。可能有一种 ImageReaderSpi 实现为 PNG 提供 ImageReader,另一种 ImageReaderSpi 为 JPEG 提供 ImageReader,等等。每个这样的服务提供者类(即 ImageReaderSpi 的每个具体实现)在其 canDecodeInput 中都有不同的逻辑。方法,因此不会创建重量级的 ImageReader 实例,除非应用程序确实需要它们。

But which approach is more common: to provide the configuration file among the provider, or provide the file listing a set of supported providers from within the API library itself?

如果我正确理解你的问题,答案是在实践中,SPI 描述符总是与它命名的提供程序类位于同一个 .jar 文件中。

至于你问题的最后一部分:我不认为记录器框架使用 ServiceLoader。 ServiceLoader的使用示例,查看Java SE的所有包以 .spi 结尾(java.awt.im.spi、java.nio.channels.spi、java.nio.charset.spi 等)。他们中的大多数人并没有说他们依赖于 ServiceLoader,但他们都描述了他们的查找行为,你会发现它几乎总是与 ServiceLoader 相同。

How does the service loading mechanism concerns situations, wheres there are either multiple providers with their configuration files present, or there is provider configuration file entry but not the class itself?

如果类路径中存在多个提供程序,ServiceLoader 将简单地在其 Iterator 中返回所有这些提供程序.

对于不正确的配置文件,ServiceConfigurationError从 ServiceLoader 的 Iterator 的 next() 方法中抛出。来自文档:

Error thrown when something goes wrong while loading a service provider.

This error will be thrown in the following situations:

  • The format of a provider-configuration file violates the specification;
  • An IOException occurs while reading a provider-configuration file;
  • A concrete provider class named in a provider-configuration file cannot be found;
  • A concrete provider class is not a subclass of the service class;
  • A concrete provider class cannot be instantiated; or
  • Some other kind of error occurs.

总结:

  • 服务提供者实现类通常与 META-INF/services 描述 rune 件在同一个 .jar 中。
  • 服务提供者类通常是一个轻量级类,允许应用程序访问更重量级的类,当且仅当应用程序决定它需要它们时。
  • Java SE 的许多部分都使用 ServiceLoader,尤其是 *.spi 包。
  • 如果一个服务有多个实现,所有的都在迭代器中返回。
  • 不正确的描述符会导致 ServiceConfigurationError。

关于Java ServiceLoader 解释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45387473/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com