モジュール java.base
パッケージ java.util

クラスServiceLoader<S>

  • 型パラメータ:
    S - このローダーによってロードされるサービスのタイプ
    すべての実装されたインタフェース:
    Iterable<S>

    public final class ServiceLoader<S>
    extends Object
    implements Iterable<S>
    サービスの実装をロードする機能です。

    serviceは、ゼロ、1つ、または多数のサービス・プロバイダが存在する、よく知られているインタフェースまたはクラスです。 「サービス・プロバイダ」 (または単にプロバイダ)は、よく知られているインタフェースまたはクラスを実装またはサブクラス化するクラスです。 ServiceLoaderは、アプリケーションの選択時にランタイム環境にデプロイされたサービス・プロバイダを検索してロードするオブジェクトです。 アプリケーション・コードは、サービス・プロバイダだけでなく、複数のサービス・プロバイダを区別することができ、サービス・プロバイダが存在しない可能性を扱うことができると想定されています。

    サービス・ローダーの入手

    アプリケーションは、ServiceLoaderの静的なloadメソッドの1つを呼び出して、特定のサービスのサービス・ローダーを取得します。 アプリケーションがモジュールの場合、そのモジュール宣言にはサービスを指定するusesディレクティブ文が必要です。プロバイダの場所を特定し、確実に実行されるようにします。 さらに、サービスがアプリケーション・モジュールにない場合、モジュール宣言には、サービスをエクスポートするモジュールを指定するrequiresディレクティブ文がなければなりません。

    サービス・ローダーを使用して、iteratorメソッドを使用してサービスのプロバイダを特定し、インスタンス化することができます。 ServiceLoaderは、streamメソッドを定義して、インスタンス化せずに検査およびフィルタリングできるプロバイダのストリームを取得します。

    例として、サービスがエンコーダとデコーダを生成するためのメソッドを定義するインタフェースであるcom.example.CodecFactoryであるとします:

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

    次のコードは、CodecFactoryサービスのサービス・ローダーを取得し、そのイテレータ(enhanced-forループによって自動的に作成される)を使用して、配置されているサービス・プロバイダのインスタンスを生成します:

    
         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;
             }
     

    このコードがモジュールにある場合、com.example.CodecFactoryインタフェースを参照するために、モジュール宣言にはインタフェースをエクスポートするモジュールが必要です。 モジュール宣言では、com.example.CodecFactoryの使用も指定します:

    
         requires com.example.codec.core;
         uses com.example.CodecFactory;
     

    サービス・プロバイダをインスタンス化する前に、そのサービス・プロバイダのインスタンスが有用かどうかを判断するために、アプリケーションがサービス・プロバイダを検査することが必要な場合があります。 例えば、 CodecFactoryのサービス・プロバイダは、"PNG"エンコーダを生成することができ、@PNGで注釈を付けることができます。 次のコードは、イテレータがCodecFactoryのインスタンスを生成する方法とは対照的に、サービス・ローダーstreamメソッドを使用してProvider<CodecFactory>のインスタンスを生成します:

    
         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());
     
    1. Provider<CodecFactory>オブジェクトのストリーム
    2. p.type()Class<CodecFactory>を生成
    3. get()CodecFactoryのインスタンスを生成

    サービスの設計

    サービスは単一のタイプです。通常、インタフェースまたは抽象クラスです。 具体的なクラスを使用できますが、これはお勧めしません。 型にはアクセシビリティがある可能性があります。 サービスのメソッドは高度にドメイン固有であるため、このAPI仕様ではフォームまたは関数について具体的なアドバイスを行うことはできません。 ただし、一般的なガイドラインは2つあります:

    1. サービスは、サービス・プロバイダがドメイン固有のプロパティやその他の実装品質の要素を伝えるために必要な数のメソッドを宣言する必要があります。 次に、サービスのサービス・ローダーを取得するアプリケーションは、アプリケーションのベスト・プロバイダを選択するために、サービス・プロバイダの各インスタンスでこれらのメソッドを呼び出すことができます。

    2. サービスは、そのサービス・プロバイダがサービスの直接実装を意図しているのか、"proxy"や"factory"などの間接的なメカニズムであるのかを表現する必要があります。 サービス・プロバイダは、ドメイン固有のオブジェクトがインスタンス化するのに比較的高価な場合は間接的なメカニズムになりがちです。この場合、サービス・プロバイダは、オンデマンドで"real"実装を作成する抽象であるように設計する必要があります。 たとえば、CodecFactoryサービスは、サービス・プロバイダがコーデック自体ではなくコーデックのファクトリであることをその名前で表しています。これは、特定のコーデックを生成するのが高価で複雑な場合があるためです。

    サービス・プロバイダの開発

    サービス・プロバイダは単一のタイプです。通常、コンクリート・クラスです。 インタフェースまたは抽象クラスは、後述する静的プロバイダ・メソッドを宣言できるため、許可されています。 型はパブリックである必要があり、内部クラスであってはなりません。

    サービス・プロバイダとそのサポート・コードは、モジュールで開発され、アプリケーション・モジュールのパスまたはイメージにデプロイされます。 あるいは、サービス・プロバイダとそのサポート・コードをJARファイルとしてパッケージ化し、アプリケーション・クラス・パスにデプロイすることもできます。 モジュール内でサービス・プロバイダを開発する利点は、その実装のすべての詳細を隠すためにプロバイダを完全にカプセル化できることです。

    特定のサービスのサービス・ローダーを取得するアプリケーションは、そのサービスのプロバイダがモジュールにデプロイされているのかJARファイルとしてパッケージ化されているのかは無関係です。 アプリケーションは、サービス・ローダー・イテレータを介してサービス・プロバイダをインスタンス化するか、またはサービス・ローダー・ストリームのProviderオブジェクトを介して、サービス・プロバイダのロケーションを知らずにインスタンス化します。

    サービス・プロバイダをモジュールとしてデプロイ

    モジュールで開発されるサービス・プロバイダは、モジュール宣言のprovidesディレクティブで指定する必要があります。 provideディレクティブは、サービスとサービス・プロバイダの両方を指定します。これは、サービスのusesディレクティブを持つ別のモジュールがサービスのサービス・ローダーを取得したときに、プロバイダの位置を特定するのに役立ちます。 モジュールがサービス・プロバイダを含むパッケージをエクスポートしないことを強くお勧めします。 providesディレクティブで、別のモジュールのサービス・プロバイダを指定するモジュールのサポートはありません。

    モジュール内で開発されたサービス・プロバイダは、インスタンス化された時点を制御できません。これは、アプリケーションの要求に応じて発生するためですが、インスタンス化の方法を制御します:

    • サービス・プロバイダがプロバイダ・メソッドを宣言すると、サービス・ローダーはそのメソッドを呼び出して、サービス・プロバイダのインスタンスを取得します。 プロバイダ・メソッドは、公式の静的メソッド"provider"で、仮パラメータはなく、戻り値の型はサービス・インタフェースまたはクラスに割り当てられます。

      この場合、サービス・プロバイダ自体をサービス・インタフェースまたはクラスに割り当てる必要はありません。

    • サービス・プロバイダがプロバイダ・メソッドを宣言しない場合、サービス・プロバイダはプロバイダ・コンストラクタを介して直接インスタンス化されます。 プロバイダ・コンストラクタは、仮パラメータを持たないパブリック・コンストラクタです。

      この場合、サービス・プロバイダはサービス・インタフェースまたはクラスに割り当てる必要があります

    アプリケーション・モジュールのパスに「自動モジュール」としてデプロイされるサービス・プロバイダには、プロバイダ・コンストラクタが必要です。 この場合、プロバイダ・メソッドはサポートされていません。

    たとえば、モジュールが次のディレクティブを指定したとします:

    
         provides com.example.CodecFactory with com.example.impl.StandardCodecs;
         provides com.example.CodecFactory with com.example.impl.ExtendedCodecsFactory;
     

    where

    • com.example.CodecFactoryは、以前の2メソッド・サービスです。
    • com.example.impl.StandardCodecsは、CodecFactoryを実装し、public no-argsコンストラクタを持つパブリック・クラスです。
    • com.example.impl.ExtendedCodecsFactoryは、CodecFactoryを実装していないパブリック・クラスですが、戻り値の型がCodecFactoryの"provider"という引数を持たないpublic staticメソッドを宣言しています。

    サービス・ローダーは、そのコンストラクタを介してStandardCodecsをインスタンス化し、そのproviderメソッドを呼び出すことによってExtendedCodecsFactoryをインスタンス化します。 プロバイダ・コンストラクタまたはプロバイダ・メソッドがpublicであるという要件は、クラス(つまり、サービス・プロバイダ)がクラス・パッケージの外にあるエンティティ(つまり、サービス・ローダー)によってインスタンス化されるという意図を文書化するのに役立ちます。

    クラスパスにサービス・プロバイダをデプロイ

    クラスパスのJARファイルとしてパッケージ化されたサービス・プロバイダは、「プロバイダ構成ファイル」をリソース・ディレクトリMETA-INF/servicesに配置することによって識別されます。 プロバイダ構成ファイルの名前は、サービスの完全修飾バイナリ名です。 プロバイダ構成ファイルには、1行に1つずつ、サービス・プロバイダの完全修飾バイナリ名のリストが含まれています。

    たとえば、サービス・プロバイダcom.example.impl.StandardCodecsがクラスパスのJARファイルにパッケージされているとします。 JARファイルには、次の名前のプロバイダ構成ファイルが含まれます:

    META-INF/services/com.example.CodecFactory
    次の行を含む:
    com.example.impl.StandardCodecs # Standard codecs

    プロバイダ構成ファイルは、UTF-8でエンコードする必要があります。 各サービス・プロバイダ名を囲む空白文字とタブ文字は無視されます。 コメント文字は'#' ('&#92;u0023' NUMBER SIGN)です。各行で、最初のコメント文字に続くすべての文字は無視されます。 サービス・プロバイダ・クラス名がプロバイダ構成ファイルに複数回リストされている場合、その複製は無視されます。 複数の構成ファイルでサービス・プロバイダ・クラスの名前が指定されている場合、その複製は無視されます。

    プロバイダ構成ファイルに記述されているサービス・プロバイダは、プロバイダ構成ファイルと同じJARファイルまたは別のJARファイルにあります。 サービス・プロバイダは、プロバイダ構成ファイルを見つけるために最初に問合せされたクラス・ローダーから可視でなければなりません。これは必ずしも最終的にプロバイダ構成ファイルを見つけるクラス・ローダーではありません。

    プロバイダ発見のタイミング

    サービス・プロバイダは、遅延して、つまり必要に応じてロードされ、インスタンス化されます。 サービス・ローダーは、以前にロードされたプロバイダのキャッシュを維持管理します。 iteratorメソッドを呼び出すたびに、Iteratorが返され、インスタンス化された順序でキャッシュされたすべての要素が最初に生成され、残りのプロバイダが遅延検索されてインスタンス化され、それぞれがキャッシュに順番に追加されます。 同様に、streamメソッドを呼び出すと、前のストリーム操作によってロードされたすべてのプロバイダを最初に処理し、ロードされた順番にStreamが返され、残りのプロバイダが遅延探索されます。 キャッシュはreloadメソッドでクリアされます。

    Errors

    サービス・ローダーiteratorを使用する場合、サービス・プロバイダの特定、ロードまたはインスタンス化でエラーが発生すると、hasNextおよびnextメソッドはServiceConfigurationErrorで失敗します。 サービス・ローダー・ストリームを処理する場合、ServiceConfigurationErrorは、サービス・プロバイダの位置またはロードを引き起こすどのようなメソッドによってもスローされる可能性があります。

    モジュール内でサービス・プロバイダをロードまたはインスタンス化する場合、次の理由により ServiceConfigurationErrorをスローすることができます:

    • サービス・プロバイダをロードできません。
    • サービス・プロバイダは、プロバイダ・メソッドを宣言しておらず、サービス・インタフェース/クラスに割り当て可能でもプロバイダ・コンストラクタも持ちません。
    • サービス・プロバイダは、"provider"という名前の引数を持たないpublic staticメソッドを、サービス・インタフェースまたはクラスに代入不可能な戻り値の型で宣言します。
    • サービス・プロバイダ・クラス・ファイルには、"provider"という名前の引数を持たないpublic staticメソッドが複数あります。
    • サービス・プロバイダはプロバイダ・メソッドを宣言し、nullを返すか例外をスローして失敗します。
    • サービス・プロバイダはプロバイダ・メソッドを宣言せず、プロバイダ・コンストラクタは例外をスローすることによって失敗します。

    プロバイダ構成ファイルを読み込むとき、またはプロバイダ構成ファイルで指定されたプロバイダ・クラスをロードまたはインスタンス化するときは、次の理由で ServiceConfigurationErrorをスローすることができます。

    • プロバイダ構成ファイルの形式が上記のformatに違反しています。
    • IOExceptionがプロバイダ構成ファイルを読み取っているときに発生します。
    • サービス・プロバイダはロードできません。
    • サービス・プロバイダは、サービス・インタフェースまたはクラスに割り当て可能ではなく、プロバイダ・コンストラクタを定義していないか、またはインスタンス化できません。

    セキュリティ

    サービス・ローダーは、イテレータまたはストリーム・メソッドの呼び出し側のセキュリティ・コンテキストで常に実行され、サービス・ローダーを作成した呼び出し元のセキュリティ・コンテキストによっても制限される可能性があります。 信頼できるシステム・コードは通常、このクラス内のメソッドやそれらのメソッドから返されるイテレータのメソッドを、特権付きのセキュリティ・コンテキスト内から呼び出すべきです。

    並行性

    このクラスのインスタンスは、複数のスレッドで並行して使用することはできません。

    ヌル処理

    特に指定されていないかぎり、null引数をこのクラスのメソッドに渡すと、NullPointerExceptionがスローされます。

    導入されたバージョン:
    1.6
    • メソッドの詳細

      • iterator

        public Iterator<S> iterator()
        このローダーのサービスの利用可能なプロバイダを遅延的にロードしてインスタンス化するイテレータを返します。

        遅延性を実現するために、プロバイダを特定してインスタンス化する実際の作業はイテレータ自体によって行われます。 そのため、hasNextメソッドとnextメソッドは、上記の「エラー」セクションで指定された理由のいずれかによってServiceConfigurationErrorをスローすることができます。 堅牢なコードを記述するには、イテレータを使用するときにServiceConfigurationErrorをキャッチすることだけです。 エラーがスローされた場合、その後のイテレータの呼び出しは、次に使用可能なプロバイダを特定してインスタンス化するために最善の努力をしますが、一般的にこのようなリカバリは保証できません。

        キャッシング: このメソッドによって返されるイテレータは、最初にプロバイダ・キャッシュのすべての要素を、ロードされた順序で返します。 その後、残りのサービス・プロバイダを遅延的にロードしてインスタンス化し、各サービス・プロバイダを順次キャッシュに追加します。 reloadメソッドを呼び出してこのローダー・プロバイダのキャッシュをクリアすると、このサービス・ローダーの既存のイテレータは破棄されます。 イテレータの hasNextおよびnextメソッドは、プロバイダ・キャッシュがクリアされた後で使用される場合、ConcurrentModificationExceptionをスローします。

        このメソッドから返されるイテレータは、削除をサポートしません。 そのremoveメソッドを呼び出すと、UnsupportedOperationExceptionがスローされます。

        定義:
        iterator、インタフェースIterable<S>
        APIのノート:
        これらのケースでエラーを投げることは極端に思えるかもしれません。 このような動作になっている理由は、不正なプロバイダ構成ファイルは不正なクラス・ファイルと同じく、Java仮想マシンの構成方法や使用方法に関する深刻な問題を示していることにあります。 このため、復旧しようとしたり、さらに悪いことに何の通知もなく失敗したりするよりも、エラーをスローすることをお薦めします。
        戻り値:
        このローダーのサービスのプロバイダを遅延的にロードするイテレータ
      • stream

        public Stream<ServiceLoader.Provider<S>> stream()
        このローダーのサービスの利用可能なプロバイダを遅延的にロードするストリームを返します。 ストリーム要素は型Providerで、プロバイダを取得またはインスタンス化するにはProvider getメソッドを呼び出す必要があります。

        遅延性を実現するために、ストリームを処理するときにプロバイダを見つける実際の作業が行われます。 上記の「エラー」セクションで指定された理由でサービス・プロバイダをロードできない場合、サービス・プロバイダをロードする原因となったメソッドによってServiceConfigurationErrorがスローされます。

        キャッシング: ストリームを処理するとき、ストリーム操作によって以前にロードされたプロバイダがロードされた順に最初に処理されます。 その後、残りのサービス・プロバイダが遅延的にロードされます。 reloadメソッドを呼び出すことによってこのローダー・プロバイダのキャッシュがクリアされた場合、このサービス・ローダーの既存のストリームは破棄されます。 返されるストリーム・ソースspliteratorfail-fastで、プロバイダ・キャッシュがクリアされている場合はConcurrentModificationExceptionがスローされます。

        次の使用例は、使用方法を示しています。 最初の例はCodecFactoryオブジェクトのストリームを作成し、2番目の例はプロバイダ・クラス名(すべてのプロバイダを見つける)でプロバイダを並べ替える点を除いて同じです。

        
            Stream<CodecFactory> providers = ServiceLoader.load(CodecFactory.class)
                    .stream()
                    .map(Provider::get);
        
            Stream<CodecFactory> providers = ServiceLoader.load(CodecFactory.class)
                    .stream()
                    .sorted(Comparator.comparing(p -> p.type().getName()))
                    .map(Provider::get);
         

        戻り値:
        このローダー・サービスのプロバイダを遅延ロードするストリーム
        導入されたバージョン:
        9
      • load

        public static <S> ServiceLoader<S> load​(Class<S> service,
                                                ClassLoader loader)
        指定されたサービスの新しいサービス・ローダーを作成します。 サービス・ローダーは、指定されたクラス・ローダーを開始点として使用して、サービスのサービス・プロバイダを特定します。 サービス・ローダーiteratorstreamは、次のように、名前付きモジュールと名前のないモジュールの両方でプロバイダを探します:
        • ステップ1: 名前付きモジュールでプロバイダを検索します。

          サービス・プロバイダは、クラス・ローダーのすべての名前付きモジュールまたは親の委譲を介して到達可能な任意のクラス・ローダーにあります。

          さらに、クラス・ローダーがブートストラップまたは「プラットフォーム・クラス・ローダー」でない場合、サービス・プロバイダは他のクラス・ローダーの指定されたモジュールに配置されます。 具体的には、クラス・ローダーまたは親委任を介して到達可能なクラス・ローダーのモジュールが「モジュール層」内にある場合、モジュール・レイヤー内のすべてのモジュールのサービス・プロバイダが配置されます。

          たとえば、各モジュールが独自のクラス・ローダー(defineModulesWithManyLoadersを参照してください)にあるモジュール・レイヤーがあるとします。 このServiceLoader.loadメソッドが呼び出されて、モジュール・レイヤー用に作成されたクラス・ローダーのいずれかを使用してプロバイダが見つかった場合は、定義しているクラス・ローダーに関係なく、モジュール・レイヤー内のすべてのプロバイダが検索されます。

          Ordering: サービス・ローダーは、まずクラス・ローダー、親クラス・ローダー、親親などに定義されたモジュール内のサービス・プロバイダをブートストラップ・クラス・ローダーに配置します。 クラス・ローダーがモジュール・レイヤーにモジュールを持つ場合、そのモジュール・レイヤー内のすべてのプロバイダは、親クラス・ローダーのプロバイダが配置される前に(クラス・ローダーに関係なく)に配置されます。 同じクラス・ローダー内のモジュールの順序付け、またはモジュール・レイヤー内のモジュールの順序付けは定義されていません。

          モジュールが複数のプロバイダを宣言する場合、プロバイダはモジュール記述子「プロバイダを一覧表示」の順に配置されます。 エージェント(redefineModuleを参照してください)によって動的に追加されたプロバイダは、モジュールによって宣言されたプロバイダの後に常に配置されます。

        • ステップ2: 名前のないモジュールでプロバイダを検索します。

          名前のないモジュールのサービス・プロバイダは、そのクラス名がクラス・ローダーgetResourcesメソッドによって指定されたプロバイダ構成ファイルにリストされている場合に配置されます。

          順序付けは、クラス・ローダー getResourcesメソッドがサービス構成ファイルを検索する順序に基づいており、その中でクラス名がファイル内にリストされている順序に基づいています。

          プロバイダ構成ファイルでは、名前付きモジュールにデプロイされているサービス・プロバイダの記述は無視されます。 これは、名前付きモジュールにprovidesディレクティブと同じサービス・プロバイダを記述するプロバイダ構成ファイルの両方がある場合に発生する重複を避けるためです。

          プロバイダ・クラスは、クラス・ローダーから可視でなければなりません。

        APIのノート:
        クラス・ローダーのクラスパスにリモート・ネットワークURLが含まれている場合、それらのURLはプロバイダ構成ファイルの検索中に参照解除される可能性があります。

        この活動は正常ですが、その場合、Webサーバーのログ内に不可解なエントリが作成される可能性があります。 ただし、Webサーバーが正しく構成されていない場合には、この活動によってプロバイダ・ロード・アルゴリズムが擬似的に失敗する可能性があります。

        要求されたリソースが存在しない場合、WebサーバーはHTTP 404 (Not Found)応答を返すべきです。 ところが、Webサーバーのなかには、そのような場合にHTTP 200 (OK)応答と有用なHTMLエラー・ページを返すように、間違って構成されているものもあります。 その場合、このクラスがそのHTMLページをプロバイダ構成ファイルとして解析しようとした時点で、ServiceConfigurationErrorがスローされます。 この問題の最良の解決策は、間違って構成されたWebサーバーが正しい応答コード(HTTP 404)とHTMLエラー・ページを返すように、修正することです。

        型パラメータ:
        S - サービス・タイプのクラス
        パラメータ:
        service - サービスを表すインタフェースまたは抽象クラス
        loader - プロバイダ構成ファイルとプロバイダ・クラスのロードに使用するクラス・ローダー。システム・クラス・ローダー(それが失敗した場合はブートストラップ・クラス・ローダー)を使用する場合はnull
        戻り値:
        新しいサービス・ローダー
        例外:
        ServiceConfigurationError - サービス型が呼び出し元にアクセスできない場合、または呼び出し元が明示的なモジュールにあり、そのモジュール記述子がserviceを使用していると宣言していない場合
      • load

        public static <S> ServiceLoader<S> load​(Class<S> service)
        指定されたサービス・タイプの新しいサービス・ローダーを、現在のスレッドのコンテキスト・クラス・ローダーを使って作成します。

        このメソッドを次の形式で呼び出すと、上記の動作が行われます。

        
             ServiceLoader.load(service)
         
        は、次のオプションに相当します。
        
             ServiceLoader.load(service, Thread.currentThread().getContextClassLoader())
         

        APIのノート:
        このメソッドで取得されたサービス・ローダー・オブジェクトは、VM全体にキャッシュされるべきではありません。 たとえば、同じVM内の異なるアプリケーションは、異なるスレッド・コンテキスト・クラス・ローダーを持つ可能性があります。 1つのアプリケーションによるルックアップは、そのスレッド・コンテキスト・クラス・ローダーを介してしか見ることができないので、他のアプリケーションが位置するのに適していないサービス・プロバイダを見つけることができます。 メモリー・リークも発生する可能性があります。 スレッド・ローカルは、いくつかのアプリケーションに適しています。
        型パラメータ:
        S - サービス・タイプのクラス
        パラメータ:
        service - サービスを表すインタフェースまたは抽象クラス
        戻り値:
        新しいサービス・ローダー
        例外:
        ServiceConfigurationError - サービス型が呼び出し元にアクセスできない場合、または呼び出し元が明示的なモジュールにあり、そのモジュール記述子がserviceを使用していると宣言していない場合
      • loadInstalled

        public static <S> ServiceLoader<S> loadInstalled​(Class<S> service)
        「プラットフォーム・クラス・ローダー」を使用して、指定されたサービス型用の新しいサービス・ローダーを作成します。

        この便利なメソッドは、次の指定と同じです。

        
             ServiceLoader.load(service, ClassLoader.getPlatformClassLoader())
         

        このメソッドは、インストール済みのプロバイダだけが必要な場合に使用するためのものです。 結果として得られるサービスは、現在のJava仮想マシンにインストールされているプロバイダのみを検索してロードします。アプリケーション・モジュール・パスまたはクラスパス上のプロバイダは無視されます。

        型パラメータ:
        S - サービス・タイプのクラス
        パラメータ:
        service - サービスを表すインタフェースまたは抽象クラス
        戻り値:
        新しいサービス・ローダー
        例外:
        ServiceConfigurationError - サービス型が呼び出し元にアクセスできない場合、または呼び出し元が明示的なモジュールにあり、そのモジュール記述子がserviceを使用していると宣言していない場合
      • load

        public static <S> ServiceLoader<S> load​(ModuleLayer layer,
                                                Class<S> service)
        指定されたモジュール・タイプおよびその祖先のモジュールからサービス・プロバイダをロードするために、指定されたサービス・タイプ用の新しいサービス・ローダーを作成します。 名前のないモジュールにはプロバイダが置かれていません。 サービス・ローダーiteratorstreamがプロバイダとyield要素を見つける順序は、次のとおりです:
        • プロバイダは、プロバイダを親レイヤーに配置する前にモジュール・レイヤーに配置されます。 親レイヤーのトラバーサルは深度優先であり、各レイヤーは最大で1回しかアクセスされません。 たとえば、L0がブート層であり、L1およびL2がL0を親とするモジュール層であるとします。 ここで、L3がL1とL2を親(その順番で)として作成されたとします。 サービス・ローダーを使用して、コンテキストとしてL3を持つプロバイダを見つけると、次の順序でプロバイダが検索されます: L3, L1, L0, L2.

        • モジュールが複数のプロバイダを宣言する場合、プロバイダはモジュール記述子「プロバイダを一覧表示」の順に配置されます。 エージェントによって動的に追加されたプロバイダは、モジュールによって宣言されたプロバイダの後に常に配置されます。

        • モジュール・レイヤーのモジュールの順序は定義されていません。

        APIのノート:
        ここで定義されている他のロード・メソッドとは異なり、サービス型は2番目のパラメータです。 この理由は、load(S, null)を使用するコードのソースの互換性の問題を避けるためです。
        型パラメータ:
        S - サービス・タイプのクラス
        パラメータ:
        layer - モジュール層
        service - サービスを表すインタフェースまたは抽象クラス
        戻り値:
        新しいサービス・ローダー
        例外:
        ServiceConfigurationError - サービス型が呼び出し元にアクセスできない場合、または呼び出し元が明示的なモジュールにあり、そのモジュール記述子がserviceを使用していると宣言していない場合
        導入されたバージョン:
        9
      • findFirst

        public Optional<S> findFirst()
        このローダーのサービスの最初に使用可能なサービス・プロバイダをロードします。 この便利なメソッドは、iterator()メソッドを呼び出して最初の要素を取得するのと同じです。 したがって、可能であればプロバイダのキャッシュから最初の要素を返し、そうでなければ最初のプロバイダをロードしてインスタンス化しようとします。

        次の例は、最初に使用可能なサービス・プロバイダを読み込みます。 サービス・プロバイダが見つからない場合は、デフォルトの実装が使用されます。

        
            CodecFactory factory = ServiceLoader.load(CodecFactory.class)
                                                .findFirst()
                                                .orElse(DEFAULT_CODECSET_FACTORY);
         

        戻り値:
        最初のサービス・プロバイダまたはサービス・プロバイダがない場合は空のOptional
        例外:
        ServiceConfigurationError - 上記の「Errors」セクションで指定された理由のいずれかでプロバイダ・クラスをロードできない場合。
        導入されたバージョン:
        9
      • reload

        public void reload()
        このローダーのプロバイダ・キャッシュをクリアし、すべてのプロバイダが再ロードされるようにします。

        このメソッドを呼び出した後、iteratorまたはstreamメソッドを後で呼び出すと、新しく作成されたサービス・ローダーと同様に、最初からプロバイダ(iteratorの場合にインスタンス化します)を見つけることができます。

        このメソッドは、新しいサービス・プロバイダを実行中のJava仮想マシンにインストールできる状況での使用を意図しています。

      • toString

        public String toString()
        このサービスを記述した文字列を返します。
        オーバーライド:
        toString、クラスObject
        戻り値:
        説明文字列