S
- このローダーによってロードされるサービスのタイプpublic final class ServiceLoader<S> extends Object implements Iterable<S>
サービスとは、既知のインタフェースおよびクラス (通常は abstract クラス) のセットです。サービスプロバイダとは、特定のサービスの実装です。通常、プロバイダのクラスによって、サービス自体に定義されているクラスのインタフェースとサブクラスが実装されます。サービスプロバイダを Java プラットフォームの実装にインストールするときは、拡張機能の形式、つまり、拡張機能の通常のディレクトリに配置される jar ファイルの形式で行われます。プロバイダを利用可能にするには、アプリケーションのクラスパスに追加するか、プラットフォーム固有の方法を使います。
サービスはロード目的のために、単一の型、つまり単一のインタフェースまたは abstract クラスとして表現されます。(具象クラスも使用できますが、それはお勧めできません。)特定のサービスのプロバイダには、このサービスタイプをプロバイダに固有のデータやコードで拡張した、1 つ以上の具象クラスが含まれています。通常、プロバイダクラスには、プロバイダ自体がすべて含まれることはありません。要求時に実際のプロバイダを作成できるコードとともに、プロバイダが特定の要求を満たすことができるかどうかを識別するために必要な情報で構成されるプロキシになっています。プロバイダクラスの内容は、個別のサービスに大きく依存します。1 つのクラスまたはインタフェースでプロバイダクラスを統合することはできません。このため、このような型はここでは定義されていません。この機能が強制する唯一の要求は、プロバイダクラスには、ロード中にインスタンスを生成できるように、引数を取らないコンストラクタが存在しなければいけない、ということです。
サービスプロバイダは、リソースディレクトリ META-INF/services にプロバイダ構成ファイルを配置することによって識別されます。このファイルの名前は、サービスのタイプの完全指定バイナリ名になります。このファイルには、具象プロバイダクラスの完全指定バイナリ名が 1 行に 1 つずつ記述されます。それぞれの名前を囲む空白文字とタブ文字、および空白行は無視されます。コメント文字は '#' ('\u0023'、NUMBER SIGN) です。各行では、最初のコメント文字以降の文字はすべて無視されます。ファイルは UTF-8 でエンコードされている必要があります。
特定の具象プロバイダクラスが複数の構成ファイル内、または同じ構成ファイル内で繰り返し指定されている場合、重複した指定は無視されます。特定のプロバイダを指定した構成ファイルを、プロバイダ自体と同じ JAR ファイル (またはその他の配布単位) 内に含める必要はありません。このプロバイダには、構成ファイルの検索時に最初に照会されたクラスローダーからアクセスできなければいけません。そのクラスローダーは、ファイルが実際にロードされた際のクラスローダーと同一であるとは限らないことに注意してください。
プロバイダの検索とインスタンス化は、遅延的に、つまりオンデマンドで行われます。サービスローダーは、以前にロードされたプロバイダのキャッシュを維持管理します。iterator
メソッドが呼び出されるたびに、イテレータが 1 つ返されます。このイテレータはまず、キャッシュのすべての要素をインスタンス化された順番で生成し、次に、残りすべてのプロバイダを遅延的に検索してインスタンス化し、各プロバイダを順にキャッシュに追加します。reload
メソッドを使えば、キャッシュをクリアーできます。
サービスローダーは常に、呼び出し元のセキュリティーコンテキスト内で実行されます。信頼できるシステムコードは通常、このクラス内のメソッドやそれらのメソッドから返されるイテレータのメソッドを、特権付きのセキュリティーコンテキスト内から呼び出すべきです。
このクラスのインスタンスは、複数のスレッドで並行して使用することはできません。
特に指定されていないかぎり、null 引数をこのクラスのメソッドに渡すと、NullPointerException
がスローされます。
例 あるプロトコル用の一連のエンコーダ/デコーダペアを表現するために設計されたサービスタイプ com.example.CodecSet があるとします。この場合、それは次の 2 つの抽象メソッドを含む abstract クラスです。
各メソッドは適切なオブジェクトを返します。ただし、プロバイダが指定されたエンコーディングをサポートしない場合は null を返します。通常のプロバイダでは、複数のエンコーディングがサポートされています。public abstract Encoder getEncoder(String encodingName); public abstract Decoder getDecoder(String encodingName);
com.example.impl.StandardCodecs が CodecSet サービスの実装の 1 つである場合、その JAR ファイルには次の名前のファイルも含まれています。
META-INF/services/com.example.CodecSet
このファイルには、次の行が含まれます。
com.example.impl.StandardCodecs # Standard codecs
CodecSet クラスは、初期化時に単一のサービスインスタンスを作成および保存します。
private static ServiceLoader<CodecSet> codecSetLoader = ServiceLoader.load(CodecSet.class);
指定されたエンコーディング名に対応するエンコーダを検索するために、それは static ファクトリメソッドを定義します。このメソッドは、既知で使用可能なプロバイダに対して反復処理を実行し、適切なエンコーダが見つかったかプロバイダの有効期限が切れた場合にのみリターンします。
public static Encoder getEncoder(String encodingName) { for (CodecSet cp : codecSetLoader) { Encoder enc = cp.getEncoder(encodingName); if (enc != null) return enc; } return null; }
getDecoder メソッドも同様に定義されます。
使用上の注意点 プロバイダのロードに使用されるクラスローダーのクラスパスにリモートネットワーク URL が含まれている場合、プロバイダ構成ファイルの検索中にそれらの URL が間接参照されます。
この活動は正常ですが、その場合、Web サーバーのログ内に不可解なエントリが作成される可能性があります。ただし、Web サーバーが正しく構成されていない場合には、この活動によってプロバイダロードアルゴリズムが擬似的に失敗する可能性があります。
要求されたリソースが存在しない場合、Web サーバーは HTTP 404 (Not Found) 応答を返すべきです。ところが、Web サーバーのなかには、そのような場合に HTTP 200 (OK) 応答と有用な HTML エラーページを返すように、間違って構成されているものもあります。その場合、このクラスがその HTML ページをプロバイダ構成ファイルとして解析しようとした時点で、ServiceConfigurationError
がスローされます。この問題の最良の解決策は、間違って構成された Web サーバーが正しい応答コード (HTTP 404) と HTML エラーページを返すように、修正することです。
修飾子と型 | メソッドと説明 |
---|---|
Iterator<S> |
iterator()
このローダーのサービスの使用可能なプロバイダを、遅延的にロードします。
|
static <S> ServiceLoader<S> |
load(Class<S> service)
指定されたサービスタイプの新しいサービスローダーを、現在のスレッドのコンテキストクラスローダーを使って作成します。
|
static <S> ServiceLoader<S> |
load(Class<S> service, ClassLoader loader)
指定されたサービスタイプとクラスローダーに対応する新しいサービスローダーを作成します。
|
static <S> ServiceLoader<S> |
loadInstalled(Class<S> service)
指定されたサービスタイプの新しいサービスローダーを、拡張クラスローダーを使って作成します。
|
void |
reload()
このローダーのプロバイダキャッシュをクリアーし、すべてのプロバイダが再ロードされるようにします。
|
String |
toString()
このサービスを記述した文字列を返します。
|
public void reload()
このメソッドが呼び出されると、iterator
メソッドの後続の呼び出しは、作成されたばかりのローダーが行うのとまったく同様に、プロバイダを一から遅延的に検索およびインスタンス化します。
このメソッドは、実行中の Java 仮想マシン内に新しいプロバイダをインストールできるような状況で使用するためのものです。
public Iterator<S> iterator()
このメソッドから返されるイテレータはまず、プロバイダキャッシュのすべての要素をインスタンス化された順番で生成します。次に、イテレータは残りすべてのプロバイダを遅延的にロードしてインスタンス化し、各プロバイダを順にキャッシュに追加します。
遅延性を実現するために、使用可能なプロバイダ構成ファイルを解析し、プロバイダをインスタンス化するという実際の作業は、イテレータ自体によって行われます。したがって、その hasNext
および next
メソッドは、プロバイダ構成ファイルが指定された形式に違反している場合、検索およびインスタンス化できないプロバイダクラスがプロバイダ構成ファイル内に指定されていた場合、クラスをインスタンス化した結果をサービスタイプに代入できない場合、または次のプロバイダを検索およびインスタンス化する際にその他のあらゆる種類の例外やエラーがスローされた場合に、ServiceConfigurationError
をスローする可能性があります。サービスイテレータを使用する場合に、堅牢なコードを記述するために必要なことは、ServiceConfigurationError
をキャッチすることだけです。
そのようなエラーがスローされた場合、イテレータの後続の呼び出しは最善の努力を尽くして、次に使用可能なプロバイダを検索およびインスタンス化しようとしますが、一般に、そのような復旧は必ずしも成功するとはかぎりません。
設計上の注意点 これらの場合にエラーをスローすることは、極端に見えるかもしれません。このような動作になっている理由は、不正なプロバイダ構成ファイルは不正なクラスファイルと同じく、Java 仮想マシンの構成方法や使用方法に関する深刻な問題を示していることにあります。このため、復旧しようとしたり、さらに悪いことに何の通知もなく失敗したりするよりも、エラーをスローすることをお勧めします。
このメソッドから返されるイテレータは、削除をサポートしません。その remove
メソッドを呼び出すと、UnsupportedOperationException
がスローされます。
public static <S> ServiceLoader<S> load(Class<S> service, ClassLoader loader)
service
- サービスを表すインタフェースまたは abstract クラスloader
- プロバイダ構成ファイルとプロバイダクラスのロードに使用するクラスローダー。システムクラスローダー (それが失敗した場合はブートストラップクラスローダー) を使用する場合は nullpublic static <S> ServiceLoader<S> load(Class<S> service)
このメソッドを次の形式で呼び出すと、上記の動作が行われます。
これは、次のように指定することと同じです。ServiceLoader.load(service)
ServiceLoader.load(service, Thread.currentThread().getContextClassLoader())
service
- サービスを表すインタフェースまたは abstract クラスpublic static <S> ServiceLoader<S> loadInstalled(Class<S> service)
この簡易メソッドは単純に、拡張クラスローダーを検索し (これを extClassLoader とする)、次の値を返します
ServiceLoader.load(service, extClassLoader)
拡張クラスローダーが見つからない場合はシステムクラスローダーが使用され、システムクラスローダーが存在しない場合はブートストラップクラスローダーが使用されます。
このメソッドは、インストール済みのプロバイダだけが必要な場合に使用するためのものです。結果として得られるサービスは、現在の Java 仮想マシンにインストールされているプロバイダだけを検索およびロードします。アプリケーションのクラスパス上のプロバイダは無視されます。
service
- サービスを表すインタフェースまたは abstract クラス バグまたは機能を送信
詳細な API リファレンスおよび開発者ドキュメントについては、Java SE のドキュメントを参照してください。そのドキュメントには、概念的な概要、用語の定義、回避方法、有効なコード例などの、開発者を対象にしたより詳細な説明が含まれています。
Copyright © 1993, 2013, Oracle and/or its affiliates. All rights reserved.