- 型パラメータ:
S
- このローダーによってロードされるサービスのタイプ
- すべての実装されたインタフェース:
Iterable<S>
serviceは、ゼロ、1つ、または多数のサービス・プロバイダが存在する、よく知られているインタフェースまたはクラスです。 「サービス・プロバイダ」 (または単にprovider)は、よく知られているインタフェースまたはクラスを実装またはサブクラス化するクラスです。 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
で注釈を付けることができます。 次のコードは、サービス・ローダーの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());
-
Provider<CodecFactory>
オブジェクトのストリーム -
p.type()
はClass<CodecFactory>
を生成 -
get()
はCodecFactory
のインスタンスを生成
サービスの設計
サービスは単一のタイプです。通常、インタフェースまたは抽象クラスです。 具体的なクラスを使用できますが、これはお勧めしません。 型にはアクセシビリティがある可能性があります。 サービスのメソッドは高度にドメイン固有であるため、このAPI仕様ではフォームまたは関数について具体的なアドバイスを行うことはできません。 ただし、一般的なガイドラインは2つあります:
サービスは、サービス・プロバイダがドメイン固有のプロパティやその他の実装品質のファクタを伝えるために必要な数のメソッドを宣言する必要があります。 次に、サービスのサービス・ローダーを取得するアプリケーションは、アプリケーションのベスト・プロバイダを選択するために、サービス・プロバイダの各インスタンスでこれらのメソッドを呼び出すことができます。
サービスは、そのサービス・プロバイダがサービスの直接実装を意図しているのか、"proxy"や"factory"などの間接的なメカニズムであるのかを表現する必要があります。 サービス・プロバイダは、ドメイン固有のオブジェクトがインスタンス化するのに比較的高価な場合は間接的なメカニズムになりがちです。この場合、サービス・プロバイダは、オンデマンドで"real"実装を作成する抽象であるように設計する必要があります。 たとえば、
CodecFactory
サービスは、サービス・プロバイダがコーデック自体ではなくコーデックのファクトリであることをその名前で表しています。これは、特定のコーデックを生成するのが高価で複雑な場合があるためです。
サービス・プロバイダの開発
サービス・プロバイダは単一のタイプです。通常、コンクリート・クラスです。 インタフェースまたは抽象クラスは、後述する静的プロバイダ・メソッドを宣言できるため、許可されています。 型はパブリックである必要があり、内部クラスであってはなりません。
サービス・プロバイダとそのサポート・コードは、モジュールで開発され、アプリケーション・モジュールのパスまたはイメージにデプロイされます。 あるいは、サービス・プロバイダとそのサポート・コードをJARファイルとしてパッケージ化し、アプリケーション・クラス・パスにデプロイすることもできます。 モジュール内でサービス・プロバイダを開発する利点は、その実装のすべての詳細を隠すためにプロバイダを完全にカプセル化できることです。
特定のサービスのサービス・ローダーを取得するアプリケーションは、そのサービスのプロバイダがモジュールにデプロイされているのかJARファイルとしてパッケージ化されているのかは無関係です。 アプリケーションは、サービス・プロバイダのロケーションを把握せずに、サービス・ローダー・イテレータを介して、またはサービス・ローダー・ストリーム内のProvider
オブジェクトを介してサービス・プロバイダをインスタンス化します。
サービス・プロバイダをモジュールとしてデプロイ
モジュールで開発されるサービス・プロバイダは、モジュール宣言のprovidesディレクティブで指定する必要があります。 provideディレクティブは、サービスとサービス・プロバイダの両方を指定します。これは、サービスのusesディレクティブを持つ別のモジュールがサービスのサービス・ローダーを取得したときに、プロバイダの位置を特定するのに役立ちます。 モジュールがサービス・プロバイダを含むパッケージをエクスポートしないことを強くお勧めします。 providesディレクティブで、別のモジュールのサービス・プロバイダを指定するモジュールのサポートはありません。
モジュール内で開発されたサービス・プロバイダは、インスタンス化された時点を制御できません。これは、アプリケーションの要求に応じて発生するためですが、インスタンス化の方法を制御します:
- サービス・プロバイダがプロバイダ・メソッドを宣言すると、サービス・ローダーはそのメソッドを呼び出して、サービス・プロバイダのインスタンスを取得します。 プロバイダ・メソッドは、"provider"という名前のパブリック静的メソッドで、仮パラメータおよびサービスのインタフェースまたはクラスに割り当てることができる戻り型はありません。
この場合、サービス・プロバイダ自体をサービスのインタフェースまたはクラスに割り当てる必要はありません。
- サービス・プロバイダがプロバイダ・メソッドを宣言しない場合、サービス・プロバイダはプロバイダ・コンストラクタを介して直接インスタンス化されます。 プロバイダ・コンストラクタは、仮パラメータを持たないパブリック・コンストラクタです。
この場合、サービス・プロバイダはサービスのインタフェースまたはクラスに割り当てることができる必要があります
アプリケーション・モジュールのパスに「自動モジュール」としてデプロイされるサービス・プロバイダには、プロバイダ・コンストラクタが必要です。 この場合、プロバイダ・メソッドはサポートされていません。
たとえば、モジュールで次のディレクティブが指定されているとします:
provides com.example.CodecFactory with com.example.impl.StandardCodecs,
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 no-argsメソッドを宣言しています。
サービス・ローダーは、そのコンストラクタを介して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でエンコードする必要があります。 各サービス・プロバイダ名を囲む空白文字とタブ文字は無視されます。 コメント文字は'#'
(U+0023
NUMBER SIGN)です。各行で、最初のコメント文字に続くすべての文字は無視されます。 サービス・プロバイダ・クラス名がプロバイダ構成ファイルに複数回リストされている場合、その複製は無視されます。 複数の構成ファイルでサービス・プロバイダ・クラスの名前が指定されている場合、その複製は無視されます。
プロバイダ構成ファイルに記述されているサービス・プロバイダは、プロバイダ構成ファイルと同じJARファイルまたは別のJARファイルにあります。 サービス・プロバイダは、プロバイダ構成ファイルを見つけるために最初に照会されたクラス・ローダーから可視でなければなりません。これは必ずしも最終的にプロバイダ構成ファイルを見つけるクラス・ローダーではありません。
プロバイダ発見のタイミング
サービス・プロバイダは、遅延して、つまり必要に応じてロードされ、インスタンス化されます。 サービス・ローダーは、以前にロードされたプロバイダのキャッシュを維持管理します。 iterator
メソッドを呼び出すたびに、Iterator
が返され、インスタンス化された順序でキャッシュされたすべての要素が最初に生成され、残りのプロバイダが遅延検索されてインスタンス化され、それぞれがキャッシュに順番に追加されます。 同様に、streamメソッドを呼び出すと、前のストリーム操作によってロードされたすべてのプロバイダを最初に処理し、ロードされた順番にStream
が返され、残りのプロバイダが遅延探索されます。 キャッシュはreload
メソッドでクリアされます。
Errors
サービス・ローダーのiterator
を使用すると、サービス・プロバイダの検索、ロードまたはインスタンス化でエラーが発生すると、hasNext
およびnext
メソッドはServiceConfigurationError
で失敗します。 サービス・ローダーのストリームを処理する場合、サービス・プロバイダを検出またはロードするメソッドによってServiceConfigurationError
がスローされることがあります。
モジュール内でサービス・プロバイダをロードまたはインスタンス化する場合、次の理由により ServiceConfigurationError
をスローすることができます:
- サービス・プロバイダをロードできません。
- サービス・プロバイダはプロバイダ・メソッドを宣言せず、サービスのインタフェース/クラスに割り当てられないか、プロバイダ・コンストラクタを持っていません。
- サービス・プロバイダは、"provider"という名前のpublic static no-argsメソッドを、サービスのインタフェースまたはクラスに割り当てられない戻り型で宣言します。
- サービス・プロバイダ・クラス・ファイルには、"
provider
"という名前のpublic static no-argsメソッドが複数あります。 - サービス・プロバイダはプロバイダ・メソッドを宣言し、
null
を返すか例外をスローして失敗します。 - サービス・プロバイダはプロバイダ・メソッドを宣言せず、プロバイダ・コンストラクタは例外をスローすることによって失敗します。
プロバイダ構成ファイルを読み込むとき、またはプロバイダ構成ファイルで指定されたプロバイダ・クラスをロードまたはインスタンス化するときは、次の理由で ServiceConfigurationError
をスローすることができます:
- プロバイダ構成ファイルの形式が上記のformatに違反しています。
-
IOException
がプロバイダ構成ファイルを読み取っているときに発生 - サービス・プロバイダはロードできません。
- サービス・プロバイダは、サービスのインタフェースまたはクラスに割り当てることができないか、プロバイダ・コンストラクタを定義しないか、またはインスタンス化できません。
セキュリティ
サービス・ローダーは、イテレータまたはストリーム・メソッドの呼出し元のセキュリティ・コンテキストで常に実行され、サービス・ローダーを作成した呼出し元のセキュリティ・コンテキストによっても制限されます。 信頼できるシステム・コードは通常、このクラス内のメソッドやそれらのメソッドから返されるイテレータのメソッドを、特権付きのセキュリティ・コンテキスト内から呼び出すべきです。
同時実行性
このクラスのインスタンスは、複数のスレッドで並行して使用することはできません。
ヌル処理
特に指定しないかぎり、このクラスのメソッドにnull
引数を渡すと、NullPointerException
がスローされます。
- 導入されたバージョン:
- 1.6
-
ネストされたクラスのサマリー
-
メソッドのサマリー
修飾子と型メソッド説明このローダーのサービスの最初の使用可能なサービス・プロバイダをロードします。iterator()
このローダーのサービスの使用可能なプロバイダを遅延的にロードおよびインスタンス化するイテレータを返します。static <S> ServiceLoader
<S> 指定されたサービス・タイプの新しいサービス・ローダーを、現在のスレッドのコンテキスト・クラス・ローダーを使って作成します。static <S> ServiceLoader
<S> load
(Class<S> service, ClassLoader loader) 指定されたサービスの新しいサービス・ローダーを作成します。static <S> ServiceLoader
<S> load
(ModuleLayer layer, Class<S> service) 指定されたモジュール・タイプおよびその祖先のモジュールからサービス・プロバイダをロードするために、指定されたサービス・タイプ用の新しいサービス・ローダーを作成します。static <S> ServiceLoader
<S> loadInstalled
(Class<S> service) 「プラットフォーム・クラス・ローダー」を使用して、指定されたサービス・タイプの新しいサービス・ローダーを作成します。void
reload()
このローダーのプロバイダ・キャッシュをクリアし、すべてのプロバイダが再ロードされるようにします。stream()
このローダーのサービスの使用可能なプロバイダを遅延的にロードするストリームを返します。toString()
このサービスを記述した文字列を返します。クラスjava.lang.Objectで宣言されたメソッド
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
インタフェースjava.lang.Iterableで宣言されたメソッド
forEach, spliterator
-
メソッドの詳細
-
iterator
このローダーのサービスの使用可能なプロバイダを遅延的にロードおよびインスタンス化するイテレータを返します。怠惰を達成するために、プロバイダを特定してインスタンス化する実際の作業はイテレータ自体によって行われます。 そのため、
hasNext
メソッドとnext
メソッドは、上記の「エラー」セクションで指定された理由のいずれかによってServiceConfigurationError
をスローすることができます。 ロバストなコードを書くには、イテレータを使用するときにServiceConfigurationError
を捕捉するだけでよい。 エラーがスローされた場合、その後のイテレータの呼び出しは、次に使用可能なプロバイダを特定してインスタンス化するために最善の努力をしますが、一般的にこのようなリカバリは保証できません。キャッシング: このメソッドによって返されるイテレータは、最初にプロバイダ・キャッシュのすべての要素を、ロードされた順序で返します。 その後、残りのサービス・プロバイダを遅延ロードしてインスタンス化し、各サービス・プロバイダを順次キャッシュに追加します。 このローダー・プロバイダ・キャッシュが
reload
メソッドを呼び出してクリアされた場合、このサービス・ローダーの既存のイテレータは破棄する必要があります。 イテレータのhasNext
およびnext
メソッドは、プロバイダ・キャッシュがクリアされた後にConcurrentModificationException
をスローします。このメソッドから返されるイテレータは、削除をサポートしません。 その
remove
メソッドを呼び出すと、UnsupportedOperationException
がスローされます。 -
stream
public Stream<ServiceLoader.Provider<S>> stream()このローダーのサービスの使用可能なプロバイダを遅延的にロードするストリームを返します。 ストリーム要素はProvider
型で、プロバイダを取得またはインスタンス化するには、Provider
のget
メソッドを起動する必要があります。怠惰を達成するために、ストリームを処理するときにプロバイダを見つける実際の作業が行われます。 上記の「エラー」セクションで指定された理由でサービス・プロバイダをロードできない場合、サービス・プロバイダをロードする原因となったメソッドによって
ServiceConfigurationError
がスローされます。キャッシング: ストリームを処理するとき、ストリーム操作によって以前にロードされたプロバイダがロードされた順に最初に処理されます。 その後、残りのサービス・プロバイダが遅延ロードされます。 このローダーのプロバイダ・キャッシュが
reload
メソッドを呼び出してクリアされた場合、このサービス・ローダーの既存のストリームは破棄する必要があります。 返されたストリームのソースspliterator
はfail-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) 指定されたサービスの新しいサービス・ローダーを作成します。 サービス・ローダーは、指定されたクラス・ローダーを開始点として使用して、サービスのサービス・プロバイダを特定します。 サービス・ローダーの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
このローダーのサービスの最初の使用可能なサービス・プロバイダをロードします。 このコンビニエンス・メソッドは、iterator()
メソッドを呼び出して最初の要素を取得することと同じです。 したがって、可能な場合はプロバイダ・キャッシュから最初の要素を返し、それ以外の場合は最初のプロバイダのロードとインスタンス化を試みます。次の例は、最初に利用可能なサービス・プロバイダを読み込みます。 サービス・プロバイダが見つからない場合は、デフォルトの実装が使用されます。
CodecFactory factory = ServiceLoader.load(CodecFactory.class) .findFirst() .orElse(DEFAULT_CODECSET_FACTORY);
- 戻り値:
- 最初のサービス・プロバイダまたはサービス・プロバイダがない場合は空の
Optional
- 例外:
ServiceConfigurationError
- 上記の「エラー」セクションで指定された理由のいずれかでプロバイダ・クラスをロードできない場合。- 導入されたバージョン:
- 9
-
reload
-
toString
-