文档说明

一个简单的service-provider加载器

service就是接口和抽象类的集合。service provider就是特定的service实现。这些提供者中的类通常实现服务本身中定义的接口和子类。service provider可以以扩展的形式安装在Java平台的实现中,即放置在JAR文件中任何普通的扩展目录中。提供者也可以通过将它们添加到应用程序的类路径或者通过其他特定于平台的方法获得。

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

服务提供者由放置在资源目录的META-INF/services来进行标识。文件名称是服务类型的完全限定二进制名称。这个文件包含了具体提供程序类的完全二进制名称列表,每行一个。忽略每个名称周围的空格和空行。注释字符是”#“;每行汇总,第一个注释字符之后的字符全部被忽略,文件必须UTF-8格式编码。

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

提供者被定位和实例化是惰性的,也就是随需而来的。一个service loader维护到目前为止已经加载的提供者程序的缓存。迭代器方法的每次调用都返回一个迭代器,该迭代器首先以实例化顺序生成缓存中的所有元素,然后懒散地定位和实例化任何剩余的提供程序,然后依次将每个添加到缓存中。可以通过reload方法清除缓存。

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

对于多个并发线程来说,此类的实例是不安全的。

除非另有指定,否则向该类中的任何方法传递空参数将导致引发NullPointerException。

Example:假设我们有一个服务类型com.example.CodecSet,打算为了一些协议提供一组encoder/decoder对。这个抽象类有2个抽象方法

  1. public abstract Encoder getEncoder(String encodingName);
  2. public abstract Decoder getDecoder(String encodingName);

每个方法会返回恰当的类或者null,如果提供者不支持这个encoding。通常提供者支持不仅仅一个encoding。

如果提供者com.example.impl.StandardCodecs是类CodecSet的实现,并且jar中含有文件名称是:

  1. META-INF/services/com.example.CodecSet

并且文件只有一行,如下:

  1. com.example.impl.StandardCodecs # Standard codecs

这个CodecSet将会被创建并且保存单个服务实例在初始化时:

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

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

  1. public static Encoder getEncoder(String encodingName) {
  2. for (CodecSet cp : codecSetLoader) {
  3. Encoder enc = cp.getEncoder(encodingName);
  4. if (enc != null)
  5. return enc;
  6. }
  7. return null;
  8. }

使用笔记:

  • 如果用于提供程序加载的类加载器的类路径包括远程网络URL,那么在搜索提供程序配置文件的过程中,这些URL将被取消引用。
  • 这个活动是正常的,尽管它可能导致令人费解的条目在Web服务器日志中创建。然而,如果未正确配置Web服务器,则此活动可能导致提供程序加载算法错误地失败。
  • 当请求的资源不存在时,Web服务器应该返回HTTP 404(Not Found)响应。然而,有时,Web服务器被错误地配置成在这种情况下返回HTTP 200(OK)响应以及有用的HTML错误页面。当该类试图将HTML页面解析为提供程序配置文件时,将引发ServiceConfigurationError。这个问题的最佳解决方案是修复配置错误的Web服务器,以返回正确的响应代码(HTTP 404)和HTML错误页面。

参考