ServiceLoader 类

定义

用于加载服务实现的设施。

[Android.Runtime.Register("java/util/ServiceLoader", DoNotGenerateAcw=true)]
[Java.Interop.JavaTypeParameters(new System.String[] { "S" })]
public sealed class ServiceLoader : Java.Lang.Object, IDisposable, Java.Interop.IJavaPeerable, Java.Lang.IIterable
[<Android.Runtime.Register("java/util/ServiceLoader", DoNotGenerateAcw=true)>]
[<Java.Interop.JavaTypeParameters(new System.String[] { "S" })>]
type ServiceLoader = class
    inherit Object
    interface IIterable
    interface IJavaObject
    interface IDisposable
    interface IJavaPeerable
继承
ServiceLoader
属性
实现

注解

用于加载服务实现的设施。

服务是一个已知接口或类,其中存在零、一个或多个服务提供商。 服务提供商(或仅提供程序)是实现或子类已知接口或类的类。 它是 ServiceLoader 一个对象,该对象在应用程序选择时定位并加载在运行时环境中部署的服务提供商。 应用程序代码仅引用服务,而不是服务提供商,并假定能够在多个服务提供商之间进行选择(基于它们通过服务公开的功能),并处理没有服务提供商找到的可能性。

<h2> 获取服务加载程序 </h2>

应用程序通过调用某个静态 load 方法 ServiceLoader获取给定服务的服务加载程序。 <--如果应用程序是模块,则其模块声明必须具有 指定服务的 using 指令;这有助于查找提供程序并确保它们能够可靠地执行。 此外,如果应用程序模块不包含服务,则其模块声明必须具有指定导出服务的模块的 requires 指令。 强烈建议应用程序模块不<<>要求>包含 service 提供程序的模块。--/>

服务加载程序可用于通过 #iterator() iterator 该方法查找和实例化服务的提供程序。 ServiceLoader 还定义了 #stream() stream 用于获取提供程序流的方法,这些提供程序可以进行检查和筛选,而无需实例化它们。

例如,假设服务是 com.example.CodecFactory一个接口,用于定义用于生成编码器和解码器的方法:

{@code
                package com.example;
                public interface CodecFactory {
                    Encoder getEncoder(String encodingName);
                    Decoder getDecoder(String encodingName);
                }
            }

以下代码获取服务的服务加载程序 CodecFactory ,然后使用其迭代器(由增强型循环自动创建)来生成位于的服务提供商的实例:

{@code
                ServiceLoader<CodecFactory> loader = ServiceLoader.load(CodecFactory.class);
                for (CodecFactory factory : loader) {
                    Encoder enc = factory.getEncoder("PNG");
                    if (enc != null)
                        ... use enc to encode a PNG file
                        break;
                    }
            }

有时,应用程序可能需要在实例化服务提供程序之前对其进行检查,以确定该服务提供商的实例是否有用。 例如,能够生成“PNG”编码器的 CodecFactory 服务提供商可能会被批注 @PNG。 以下代码使用服务加载程序 stream 的方法来生成 Provider<CodecFactory> 与迭代器生成实例的 CodecFactory实例相反:

{@code
                ServiceLoader<CodecFactory> loader = ServiceLoader.load(CodecFactory.class);
                Set<CodecFactory> pngFactories = loader
                       .stream()                                              // Note a below
                       .filter(p -> p.type().isAnnotationPresent(PNG.class))  // Note b
                       .map(Provider::get)                                    // Note c
                       .collect(Collectors.toSet());
            }

<ol type=“a”>li A stream of Provider<CodecFactory> objects </li li>><p.type() yields a Class<CodecFactory></li li>get() yields an instance of CodecFactory</li><></ol><>

<h2> 设计服务 </h2>

服务是单个类型,通常是接口或抽象类。 可以使用具体类,但不建议这样做。 该类型可能具有任何辅助功能。 服务的方法非常特定于域,因此此 API 规范无法提供有关其形式或功能的具体建议。 但是,有两个一般准则: <ol><li>

服务应根据需要声明尽可能多的方法,以允许服务提供商传达其特定于域的属性和其他实现质量因素。 获取服务的服务加载程序的应用程序随后可以在服务提供商的每个实例上调用这些方法,以便为应用程序选择最佳提供程序。

</li li><>

服务应表示其服务提供商是直接实现服务还是作为间接机制,例如“代理”或“工厂”。 当特定于域的对象相对昂贵,实例化时,服务提供商往往是间接机制;在这种情况下,应设计服务,以便服务提供商是按需创建“真实”实现的抽象。 例如, CodecFactory 该服务通过其名称表示,其服务提供商是编解码器的工厂,而不是编解码器本身,因为生成某些编解码器可能很昂贵或复杂。

</li></ol>

<h2> “developing-service-providers<”>开发服务提供商/h2>

服务提供商是单个类型,通常是具体类。 允许接口或抽象类,因为它可以声明静态提供程序方法,稍后讨论。 该类型必须是公共的,并且不能是内部类。

服务提供商及其支持代码可以在模块中开发,然后部署在应用程序模块路径或模块化映像上。 或者,服务提供商及其支持代码可以打包为 JAR 文件,并将其部署到应用程序类路径上。 在模块中开发服务提供商的优点是,提供程序可以完全封装以隐藏其实现的所有详细信息。

获取给定服务的服务加载程序的应用程序对服务提供程序是部署在模块中还是打包为 JAR 文件不一致。 应用程序通过服务加载器的迭代器或通过 Provider Provider 服务加载程序流中的对象实例化服务提供商,而无需了解服务提供商的位置。

<h2> 在类路径 </h2 上部署服务提供商>

将提供程序作为类路径的 JAR 文件打包的服务提供商通过在资源目录中META-INF/services放置提供程序配置文件来标识。 提供程序配置文件的名称是服务的完全限定二进制名称。 提供程序配置文件包含服务提供商的完全限定二进制名称的列表,每行一个。

例如,假设服务提供商 com.example.impl.StandardCodecs 打包在类路径的 JAR 文件中。 JAR 文件将包含名为:

<blockquote/blockquote>META-INF/services/com.example.CodecFactory<>

包含行:

<blockquote/blockquote>com.example.impl.StandardCodecs # Standard codecs<>

“format”>提供程序配置文件必须在 UTF-8 中编码。 将忽略每个服务提供商名称周围的空格和制表符以及空白行。 批注字符为 '#'U+0023<span style=“font-size:smaller;”>NUMBER SIGN</span>; 在每行上,将忽略第一个注释字符后面的所有字符。 如果在提供程序配置文件中多次列出服务提供程序类名称,则忽略重复项。 如果服务提供程序类在多个配置文件中命名,则忽略重复项。

提供程序配置文件中提到的服务提供商可能位于与提供程序配置文件相同的 JAR 文件或不同的 JAR 文件中。 服务提供程序必须从最初查询的类加载程序中可见以查找提供程序配置文件;这不一定是最终找到提供程序配置文件的类加载程序。

<h2> 提供程序发现 <计时 /h2>

服务提供商加载并实例化延迟,即按需实例化。 服务加载程序维护到目前为止已加载的提供程序的缓存。 该方法的每个调用 iterator 都会返回一个,它首先以实例化顺序生成从上一 Iterator 次迭代缓存的所有元素,然后延迟定位并实例化所有剩余的提供程序,并依次将每个元素添加到缓存中。 同样,每次调用流方法都会返回一个 Stream 先处理以前流操作加载的所有提供程序,按加载顺序处理所有提供程序,然后懒散地查找任何剩余的提供程序。 缓存通过 #reload reload 该方法清除。

<h2> “errors”>Errors</h2>

使用服务加载程序 iterator时, Iterator#hasNext() hasNext 如果查找、加载或实例化服务提供程序时出错,则该方法将 Iterator#next() next 失败 ServiceConfigurationError 。 处理服务加载程序流 ServiceConfigurationError 时,可能会由导致服务提供商定位或加载的任何方法引发。

在模块中加载或实例化服务提供商时, ServiceConfigurationError 可能会出于以下原因引发:

读取提供程序配置文件或加载或实例化在提供程序配置文件中命名的提供程序类时, ServiceConfigurationError 可能会引发以下原因:

<ul>

<li> 提供程序配置文件的格式违反了上面指定的格式: </li>

<读取提供程序配置文件时发生 li> An IOException IOException ; </li>

<无法加载 li> A 服务提供商; </li>

<li> A service provider is not assignable to the service's interface or class, or not define a provider constructor, or cannot be instantiated. </li>

</ul>

<h2> 并发 </h2>

此类的实例不适用于多个并发线程使用。

<h3> Null 处理 </h3>

除非另行指定,否则将参数传递给 null 此类中的任何方法将导致 NullPointerException 引发。

已在 1.6 中添加。

Java文档java.util.ServiceLoader

本页的某些部分是根据 Android 开放源代码项目创建和共享的工作进行的修改,并根据 Creative Commons 2.5 属性许可证中所述的术语使用。

属性

名称 说明
Class

返回此 Object的运行时类。

(继承自 Object)
Handle

基础 Android 实例的句柄。

(继承自 Object)
JniIdentityHashCode

用于加载服务实现的设施。

(继承自 Object)
JniPeerMembers

用于加载服务实现的设施。

PeerReference

用于加载服务实现的设施。

(继承自 Object)
ThresholdClass

此 API 支持 Mono for Android 基础结构,不打算直接从代码使用。

(继承自 Object)
ThresholdType

此 API 支持 Mono for Android 基础结构,不打算直接从代码使用。

(继承自 Object)

方法

名称 说明
Clone()

创建并返回此对象的副本。

(继承自 Object)
Dispose()

用于加载服务实现的设施。

(继承自 Object)
Dispose(Boolean)

用于加载服务实现的设施。

(继承自 Object)
Equals(Object)

指示其他对象是否“等于”此对象。

(继承自 Object)
FindFirst()

加载此加载程序服务的第一个可用服务提供商。

GetHashCode()

返回对象的哈希代码值。

(继承自 Object)
Iterator()

Lazily 加载此加载程序服务的可用提供程序。

JavaFinalize()

当垃圾回收确定不再引用该对象时,由对象上的垃圾回收器调用。

(继承自 Object)
Load(Class, ClassLoader)

为给定的服务类型和类加载程序创建新的服务加载程序。

Load(Class)

使用当前线程的 java 为给定的服务类型创建新的服务加载程序。

LoadInstalled(Class)

使用扩展类加载程序为给定的服务类型创建新的服务加载程序。

Notify()

唤醒正在等待此对象的监视器的单个线程。

(继承自 Object)
NotifyAll()

唤醒正在等待此对象的监视器的所有线程。

(继承自 Object)
Reload()

清除此加载程序提供程序缓存,以便重新加载所有提供程序。

SetHandle(IntPtr, JniHandleOwnership)

设置 Handle 属性。

(继承自 Object)
ToArray<T>()

用于加载服务实现的设施。

(继承自 Object)
ToString()

返回对象的字符串表示形式。

(继承自 Object)
UnregisterFromRuntime()

用于加载服务实现的设施。

(继承自 Object)
Wait()

使当前线程等待,直到唤醒它,通常是通过 em 通知/em< 或 >em<interrupted>/em<。><>

(继承自 Object)
Wait(Int64, Int32)

使当前线程等待直到唤醒,通常是通过 <em>通知</em> 或 <em interrupted>/em<>,或直到经过一定数量的实时。

(继承自 Object)
Wait(Int64)

使当前线程等待直到唤醒,通常是通过 <em>通知</em> 或 <em interrupted>/em<>,或直到经过一定数量的实时。

(继承自 Object)

显式接口实现

名称 说明
IJavaPeerable.Disposed()

用于加载服务实现的设施。

(继承自 Object)
IJavaPeerable.DisposeUnlessReferenced()

用于加载服务实现的设施。

(继承自 Object)
IJavaPeerable.Finalized()

用于加载服务实现的设施。

(继承自 Object)
IJavaPeerable.JniManagedPeerState

用于加载服务实现的设施。

(继承自 Object)
IJavaPeerable.SetJniIdentityHashCode(Int32)

用于加载服务实现的设施。

(继承自 Object)
IJavaPeerable.SetJniManagedPeerState(JniManagedPeerStates)

用于加载服务实现的设施。

(继承自 Object)
IJavaPeerable.SetPeerReference(JniObjectReference)

用于加载服务实现的设施。

(继承自 Object)

扩展方法

名称 说明
GetJniTypeName(IJavaPeerable)

获取实例 self类型的 JNI 名称。

JavaAs<TResult>(IJavaPeerable)

尝试强制self键入TResult,检查强制是否在Java端有效。

JavaCast<TResult>(IJavaObject)

执行 Android 运行时检查的类型转换。

JavaCast<TResult>(IJavaObject)

用于加载服务实现的设施。

ToEnumerable(IIterable)

用于加载服务实现的设施。

ToEnumerable<T>(IIterable)

用于加载服务实现的设施。

TryJavaCast<TResult>(IJavaPeerable, TResult)

尝试强制self键入TResult,检查强制是否在Java端有效。

适用于