- java.lang.Object
-
- 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());
-
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; 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でエンコードする必要があります。」各サービス・プロバイダ名を囲むスペースとタブ文字、および空白行は無視されます。 コメント文字は
'#'
('\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
-
-
ネストされたクラスのサマリー
ネストされたクラス 修飾子と型 クラス 説明 static interface
ServiceLoader.Provider<S>
ServiceLoader
が位置するサービス・プロバイダを表します。
-
メソッドのサマリー
修飾子と型 メソッド 説明 Optional<S>
findFirst()
このローダーのサービスの最初に使用可能なサービス・プロバイダをロードします。Iterator<S>
iterator()
このローダーのサービスの利用可能なプロバイダを遅延的にロードしてインスタンス化するイテレータを返します。static <S> ServiceLoader<S>
load(クラス<S> service)
指定されたサービス・タイプの新しいサービス・ローダーを、現在のスレッドのコンテキスト・クラス・ローダーを使って作成します。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(クラス<S> service)
「プラットフォーム・クラス・ローダー」を使用して、指定されたサービス型用の新しいサービス・ローダーを作成します。void
reload()
このローダーのプロバイダ・キャッシュをクリアし、すべてのプロバイダが再ロードされるようにします。Stream<ServiceLoader.Provider<S>>
stream()
このローダーのサービスの利用可能なプロバイダを遅延的にロードするストリームを返します。String
toString()
このサービスを記述した文字列を返します。-
クラス java.lang.Objectで宣言されたメソッド
clone、equals、finalize、getClass、hashCode、notify、notifyAll、wait、wait、wait
-
インタフェース java.lang.Iterableで宣言されたメソッド
forEach, spliterator
-
-
-
-
メソッドの詳細
-
iterator
public Iterator<S> 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
がプロバイダと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()
-
-