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

クラスServiceLoader<S>

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

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

    サービスは、ゼロ、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サービスのサービス・ローダーを取得し、そのイテレータ(拡張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;
     

    アプリケーションは、そのサービス・プロバイダのインスタンスが役に立つかどうかを判断するために、インスタンス化前にサービス・プロバイダを検査する必要がある場合があります。 たとえば、PNGエンコーダを生成できる CodecFactoryのサービス・プロバイダには、@PNGという注釈を付けることができます。 次のコードでは、サービス・ローダーのstreamメソッドを使用して、イテレータがCodecFactoryのインスタンスを生成する方法とは対照的に、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. サービスは、そのサービス・プロバイダがサービスの直接実装を意図しているか、「プロキシ」や「ファクトリ」などのインダイレクション・メカニズムであることを表す必要があります。 サービス・プロバイダは、ドメイン固有のオブジェクトがインスタンス化に比較的コストがかかる場合にインダイレクション・メカニズムになる傾向があります。この場合、サービス・プロバイダが、オンデマンドで実際の実装を作成する抽象化になるようにサービスを設計する必要があります。 たとえば、CodecFactoryサービスは、そのサービス・プロバイダがコーデック自体ではなくコーデックのファクトリであることを、その名前で表します。これは、特定のコーデックの生成にコストがかかるか複雑になる可能性があるためです。

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

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

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

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

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

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

    モジュール内で開発されたサービス・プロバイダは、インスタンス化のタイミングを制御できません。これは、アプリケーションの最上位で発生するためですが、インスタンス化の方法を制御できます。

    • サービス・プロバイダがプロバイダ・メソッドを宣言すると、サービス・ローダーはそのメソッドを呼び出してサービス・プロバイダのインスタンスを取得します。 providerメソッドは、"provider"という名前のpublic staticメソッドで、仮パラメータと、サービスのインタフェースまたはクラスに割り当て可能な戻り型がありません。

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

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

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

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

    たとえば、モジュールで次のディレクティブが指定されているとします。

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

    説明:

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

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

    クラス・パスへのサービス・プロバイダのデプロイ

    クラス・パスのJARファイルとしてパッケージ化されているサービス・プロバイダは、リソース・ディレクトリMETA-INF/servicesプロバイダ構成ファイルを配置することで識別されます。 provider-configurationファイルの名前は、サービスの完全修飾バイナリ名です。 provider-configurationファイルには、サービスプロバイダの完全修飾バイナリ名のリストが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が返され、最初に以前のストリーム操作によってロードされたすべてのプロバイダがロード順に処理されてから、残りのプロバイダが遅延して検索されます。 キャッシュは、reloadメソッドを使用してクリアされます。

    Errors

    サービス・ローダーのiteratorを使用すると、サービス・プロバイダの検索、ロードまたはインスタンス化でエラーが発生した場合、hasNextメソッドおよびnextメソッドはServiceConfigurationErrorで失敗します。 サービス・ローダーのストリームを処理する場合、サービス・プロバイダを検出またはロードする任意のメソッドによってServiceConfigurationErrorがスローされます。

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

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

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

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

    セキュリティ

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

    同時実行性

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

    NULL処理

    特に指定されていないかぎり、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型で、プロバイダを取得またはインスタンス化するには、Providergetメソッドを呼び出す必要があります。

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

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

        次の例は、使用方法を示しています。 1つ目の例では、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)
        指定されたサービスの新しいサービス・ローダーを作成します。 サービス・ローダーは、指定されたクラス・ローダーを開始点として使用して、サービスのサービス・プロバイダを特定します。 サービス・ローダーのiteratorおよびstreamは、次のように名前付きモジュールと名前なしモジュールの両方でプロバイダを特定します。
        • ステップ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)
        指定されたサービス・タイプの新しいサービス・ローダーを作成し、指定されたモジュール・レイヤーとその祖先内のモジュールからサービス・プロバイダをロードします。 名前のないモジュール内のプロバイダは特定されません。 サービス・ローダーのiteratorおよびstreamがプロバイダおよび歩留まり要素を見つける順序は次のとおりです。
        • プロバイダは、親レイヤーでプロバイダを見つける前にモジュール・レイヤーに配置されます。 親レイヤーのトラバースは深さ優先で、各レイヤは最大で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 - 前述の「エラー」セクションで指定した理由のいずれかでプロバイダ・クラスをロードできない場合。
        導入されたバージョン:
        9
      • reload

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

        このメソッドを起動した後、iteratorまたはstreamメソッドを後で起動すると、新しく作成されたサービス・ローダーと同様に、プロバイダがゼロから遅延して検索(およびiteratorの場合はインスタンス化)されます。

        この方法は、実行中のJava仮想マシンに新しいサービス・プロバイダをインストールできる状況で使用することを目的としています。

      • toString

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