树叶云鸿蒙OS教程:鸿蒙OS ServiceLoader

ServiceLoader

java.lang.Object

|—java.util.ServiceLoader<S&

public final class ServiceLoader<S>
extends Object
implements Iterable<S>

一个简单的服务提供者加载工具。

服务是一组众所周知的接口和(通常是抽象的)类。 服务提供者是服务的具体实现。 提供者中的类通常实现服务本身中定义的类的接口和子类。 服务提供者可以以扩展的形式安装在 Java 平台的实现中,即将 jar 文件放置在任何常用的扩展目录中。 还可以通过将提供程序添加到应用程序的类路径或通过某些其他特定于平台的方式来使提供程序可用。

出于加载的目的,服务由单一类型表示,即单一接口或抽象类。 (可以使用具体类,但不建议这样做。)给定服务的提供者包含一个或多个具体类,这些具体类使用提供者特定的数据和代码扩展此服务类型。 提供者类通常不是整个提供者本身,而是一个代理,它包含足够的信息来决定提供者是否能够满足特定请求以及可以按需创建实际提供者的代码。 提供者类的细节往往是高度特定于服务的; 没有一个类或接口可以统一它们,所以这里没有定义这样的类型。 此工具强制执行的唯一要求是提供程序类必须具有零参数构造函数,以便它们可以在加载期间被实例化。

通过在资源目录 META-INF/services 中放置提供者配置文件来识别服务提供者。 该文件的名称是服务类型的完全限定二进制名称。 该文件包含具体提供程序类的完全限定二进制名称列表,每行一个。 每个名称周围的空格和制表符以及空白行将被忽略。 注释字符为’#’(’\u0023′, NUMBER SIGN); 在每一行中,第一个注释字符之后的所有字符都将被忽略。 该文件必须以 UTF-8 编码。

如果一个特定的具体提供者类在多个配置文件中被命名,或者在同一个配置文件中被命名不止一次,那么重复的将被忽略。 命名特定提供者的配置文件不必与提供者本身位于相同的 jar 文件或其他分发单元中。 必须可以从最初查询配置文件的同一个类加载器访问提供程序; 请注意,这不一定是实际加载文件的类加载器。

提供者的定位和实例化是惰性的,即按需。 服务加载器维护到目前为止已加载的提供程序的缓存。 迭代器方法的每次调用都会返回一个迭代器,它首先按实例化顺序产生缓存的所有元素,然后延迟定位并实例化任何剩余的提供者,依次将每个提供者添加到缓存中。 可以通过 reload 方法清除缓存。

服务加载程序总是在调用者的安全上下文中执行。 受信任的系统代码通常应该从特权安全上下文中调用此类中的方法以及它们返回的迭代器的方法。

此类的实例对于多个并发线程的使用是不安全的。

除非另有说明,否则将 null 参数传递给此类中的任何方法都将导致抛出 NullPointerException。

示例 假设我们有一个服务类型 com.example.CodecSet,它旨在表示某些协议的编码器/解码器对集合。 在这种情况下,它是一个具有两个抽象方法的抽象类:

 public abstract Encoder getEncoder(String encodingName);
 public abstract Decoder getDecoder(String encodingName);

如果提供者不支持给定的编码,每个方法都会返回一个适当的对象或 null。 典型的供应商支持不止一种编码。

如果 com.example.impl.StandardCodecs 是 CodecSet 服务的实现,那么它的 jar 文件还包含一个名为

 META-INF/services/com.example.CodecSet

该文件包含一行:

 com.example.impl.StandardCodecs    # Standard codecs

CodecSet 类在初始化时创建并保存单个服务实例:

 private static ServiceLoader<CodecSet> codecSetLoader
     = ServiceLoader.load(CodecSet.class);

为了找到给定编码名称的编码器,它定义了一个静态工厂方法,该方法遍历已知和可用的提供程序,仅在找到合适的编码器或用完提供程序时返回。

 public static Encoder getEncoder(String encodingName) {
     for (CodecSet cp : codecSetLoader) {
         Encoder enc = cp.getEncoder(encodingName);
         if (enc != null)
             return enc;
     }
     return null;
 }

getDecoder 方法的定义类似。

使用说明 如果用于加载提供程序的类加载器的类路径包含远程网络 URL,则在搜索提供程序配置文件的过程中将取消引用这些 URL。

此活动是正常的,尽管它可能会导致在 Web 服务器日志中创建令人费解的条目。但是,如果未正确配置 Web 服务器,则此活动可能会导致提供程序加载算法虚假失败。

当请求的资源不存在时,Web 服务器应返回 HTTP 404(未找到)响应。但是,有时 Web 服务器被错误地配置为在这种情况下返回 HTTP 200 (OK) 响应以及有用的 HTML 错误页面。当此类尝试将 HTML 页面解析为提供程序配置文件时,这将导致抛出 ServiceConfigurationError。此问题的最佳解决方案是修复错误配置的 Web 服务器以返回正确的响应代码 (HTTP 404) 以及 HTML 错误页面。

方法总结

修饰符和类型方法描述
IteratorSiterator()延迟加载此加载程序服务的可用提供程序。
static <S> ServiceLoader<S>load(Class<S> service)使用当前线程的上下文类加载器为给定的服务类型创建一个新的服务加载器。
static <S> ServiceLoader<S>load(Class<S> service, ClassLoader loader)为给定的服务类型和类加载器创建一个新的服务加载器。
static <S> ServiceLoader<S>loadInstalled(Class<S> service)使用扩展类加载器为给定的服务类型创建一个新的服务加载器。
voidreload()清除此加载器的提供程序缓存,以便重新加载所有提供程序。
StringtoString()返回描述此服务的字符串。
从接口 java.lang.Iterable 继承的方法
forEach, spliterator
从类 java.lang.Object 继承的方法
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait

方法详情

reload

public void reload()

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

调用此方法后,迭代器方法的后续调用将懒惰地从头开始查找并实例化提供程序,就像新创建的加载程序所做的那样。

此方法适用于可以将新提供程序安装到正在运行的 Java 虚拟机中的情况。

iterator

public IteratorS iterator()

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

此方法返回的迭代器首先按实例化顺序生成提供程序缓存的所有元素。 然后它会延迟加载并实例化任何剩余的提供者,依次将每个提供者添加到缓存中。

为了实现惰性,解析可用提供程序配置文件和实例化提供程序的实际工作必须由迭代器本身完成。 因此,如果提供程序配置文件违反了指定格式,或者如果它命名了无法找到和实例化的提供程序类,或者如果实例化类的结果不能分配给服务类型,则它的 hasNext 和 next 方法可以抛出 ServiceConfigurationError ,或者在定位和实例化下一个提供程序时引发任何其他类型的异常或错误。 要编写健壮的代码,只需要在使用服务迭代器时捕获 ServiceConfigurationError。

如果抛出这样的错误,那么迭代器的后续调用将尽最大努力定位和实例化下一个可用的提供程序,但通常不能保证这样的恢复。

设计说明 在这些情况下抛出错误可能看起来很极端。 这种行为的基本原理是格式错误的提供程序配置文件(如格式错误的类文件)表明 Java 虚拟机的配置或使用方式存在严重问题。 因此,最好抛出错误而不是尝试恢复,或者更糟糕的是,静默失败。

此方法返回的迭代器不支持移除。 调用它的 remove 方法将导致抛出 UnsupportedOperationException。

指定者:

接口 IterableS 中的迭代器

返回:

延迟加载此加载器服务的提供程序的迭代器

load

public static <S> ServiceLoader<S> load(Class<S> service, ClassLoader loader)

为给定的服务类型和类加载器创建一个新的服务加载器。

类型参数:

类型参数名称类型参数描述
S服务类型的类

参数:

参数名称参数描述
service表示服务的接口或抽象类
loader用于加载提供程序配置文件和提供程序类的类加载器,如果要使用系统类加载器(或者,如果失败,则为引导类加载器),则为 null

返回:

一个新的服务加载器

load

public static <S> ServiceLoader<S> load(Class<S> service)

使用当前线程的上下文类加载器为给定的服务类型创建一个新的服务加载器。

调用表单的这种便捷方法

 ServiceLoader.load(service)

相当于

 ServiceLoader.load(service,
                    Thread.currentThread().getContextClassLoader())

类型参数:

类型参数名称类型参数描述
S服务类型的类

参数:

参数名称参数描述
service表示服务的接口或抽象类

返回:

一个新的服务加载器

loadInstalled

public static <S> ServiceLoader<S> loadInstalled(Class<S> service)

使用扩展类加载器为给定的服务类型创建一个新的服务加载器。

这个方便的方法只是简单的定位扩展类加载器,调用它extClassLoader,然后返回

 ServiceLoader.load(service, extClassLoader)

如果找不到扩展类加载器,则使用系统类加载器; 如果没有系统类加载器,则使用引导类加载器。

此方法旨在仅在需要已安装的提供程序时使用。 生成的服务只会查找并加载已安装到当前 Java 虚拟机中的提供程序; 应用程序类路径上的提供者将被忽略。

类型参数:

类型参数名称类型参数描述
S服务类型的类

参数:

参数名称参数描述
service表示服务的接口或抽象类

返回:

一个新的服务加载器

toString

public String toString()

返回描述此服务的字符串。

覆盖:

类 Object 中的 toString

返回:

描述性字符串

文章来源网络,作者:运维,如若转载,请注明出处:https://shuyeidc.com/wp/165916.html<

(0)
运维的头像运维
上一篇2025-03-20 07:24
下一篇 2025-03-20 07:25

相关推荐

  • 个人主题怎么制作?

    制作个人主题是一个将个人风格、兴趣或专业领域转化为视觉化或结构化内容的过程,无论是用于个人博客、作品集、社交媒体账号还是品牌形象,核心都是围绕“个人特色”展开,以下从定位、内容规划、视觉设计、技术实现四个维度,详细拆解制作个人主题的完整流程,明确主题定位:找到个人特色的核心主题定位是所有工作的起点,需要先回答……

    2025-11-20
    0
  • 社群营销管理关键是什么?

    社群营销的核心在于通过建立有温度、有价值、有归属感的社群,实现用户留存、转化和品牌传播,其管理需贯穿“目标定位-内容运营-用户互动-数据驱动-风险控制”全流程,以下从五个维度展开详细说明:明确社群定位与目标社群管理的首要任务是精准定位,需明确社群的核心价值(如行业交流、产品使用指导、兴趣分享等)、目标用户画像……

    2025-11-20
    0
  • 香港公司网站备案需要什么材料?

    香港公司进行网站备案是一个涉及多部门协调、流程相对严谨的过程,尤其需兼顾中国内地与香港两地的监管要求,由于香港公司注册地与中国内地不同,其网站若主要服务内地用户或使用内地服务器,需根据服务器位置、网站内容性质等,选择对应的备案路径(如工信部ICP备案或公安备案),以下从备案主体资格、流程步骤、材料准备、注意事项……

    2025-11-20
    0
  • 如何企业上云推广

    企业上云已成为数字化转型的核心战略,但推广过程中需结合行业特性、企业痛点与市场需求,构建系统性、多维度的推广体系,以下从市场定位、策略设计、执行落地及效果优化四个维度,详细拆解企业上云推广的实践路径,精准定位:明确目标企业与核心价值企业上云并非“一刀切”的方案,需先锁定目标客户群体,提炼差异化价值主张,客户分层……

    2025-11-20
    0
  • PS设计搜索框的实用技巧有哪些?

    在PS中设计一个美观且功能性的搜索框需要结合创意构思、视觉设计和用户体验考量,以下从设计思路、制作步骤、细节优化及交互预览等方面详细说明,帮助打造符合需求的搜索框,设计前的规划明确使用场景:根据网站或APP的整体风格确定搜索框的调性,例如极简风适合细线条和纯色,科技感适合渐变和发光效果,电商类则可能需要突出搜索……

    2025-11-20
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注