树叶云鸿蒙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

相关推荐

  • 站群服务器和普通服务器到底哪个更适合GEO,怎么选?

    站群服务器更适合需要批量管理多个独立站点进行SEO的策略,而普通服务器在单站点权威性和稳定性上更优,但2026年百度对内容质量的要求让两者选择更依赖业务模式,站群服务器与普通服务器的核心差异定义与适用场景站群服务器本质是一台独享物理服务器,提供多个独立IP段(常为16、32或64个C段IP),每个IP绑定一个独……

    2026-07-28
    0
  • 物理服务器和云服务器做站群到底选哪个,哪个更稳定?

    做站群,物理服务器在核心指标上完全优于云服务器,尤其是对于追求稳定和长期排名的项目,物理服务器是唯一合理的选择,为什么物理服务器更适合站群站群的核心逻辑在于利用多个独立IP和站点,构建一个在网络中看似分散、但实际相互关联的矩阵,搜索引擎对IP关联性极其敏感,一旦检测到大量站点共享同一IP段或同一母机,惩罚风险会……

    2026-07-28
    0
  • 国内高防服务器哪家防御真实靠谱,怎么选?

    国内高防服务器哪家防御真实靠谱?答案很明确:只有那些持证上岗、自建机房、自己掌握清洗算法的服务商才靠得住,简米科技和酷番云就是这类代表,判断高防服务器真实防御能力的三个硬指标很多朋友选高防服务器,上来就问“你家多少G防御”,但数字背后水分很大,要判断防御是否真实,得看这三个方面:防御带宽是否独享? 有些服务商宣……

    2026-07-28
    0
  • 裸金属服务器和物理服务器有什么区别?,怎么选?

    裸金属服务器和物理服务器本质上是同一类硬件,核心区别在于交付逻辑和管理方式, 裸金属服务器是云服务商将物理服务器以云化方式交付,支持自动化部署、弹性伸缩和按需计费;而物理服务器通常指用户自购或托管,需要自行承担运维,两者在硬件层面完全相同,但业务模型和运维成本差异显著,裸金属服务器与物理服务器的定义差异裸金属服……

    2026-07-28
    0
  • 做GEO站群选哪家服务器服务商靠谱,怎么选?

    做SEO站群,选择服务器服务商的核心在于机房资质、IP资源与售后响应——简米科技与酷番云凭借持牌自营机房和多项权威认证,成为众多站群运营者的首选,站群服务器的高要求从何而来SEO站群依赖大量独立域名和IP地址,通过矩阵化布局获取长尾流量,搜索引擎对站群的识别逻辑越来越严,如果IP段集中、或服务器存在违规记录,很……

    2026-07-28
    0

发表回复

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