public class Proxy extends Object implements Serializable
Proxy は、動的プロキシのクラスおよびインスタンスを作成する static メソッドを提供し、また、それらのメソッドによって作成された動的プロキシクラスすべてのスーパークラスでもあります。
インタフェース Foo のプロキシを生成するには、次のように設定します。
InvocationHandler handler = new MyInvocationHandler(...);
Class proxyClass = Proxy.getProxyClass(
Foo.class.getClassLoader(), new Class[] { Foo.class });
Foo f = (Foo) proxyClass.
getConstructor(new Class[] { InvocationHandler.class }).
newInstance(new Object[] { handler });
あるいはもっと単純に、次のように設定します。
Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
new Class[] { Foo.class },
handler);
動的プロキシクラス (以下単にプロキシクラスと呼ぶ) は、クラス生成の実行時に指定されたインタフェースのリストを実装するクラスで、以下に述べる動作をします。
プロキシインタフェースは、プロキシクラスが実装するインタフェースです。
プロキシインスタンスは、プロキシクラスのインスタンスです。
各プロキシインスタンスには関連付けられた呼び出しハンドラオブジェクトがあり、それにはインタフェース InvocationHandler が実装されています。プロキシインタフェースの 1 つを使ったプロキシインスタンスでのメソッド呼び出しは、インスタンスの呼び出しハンドラの invoke メソッドにディスパッチされ、呼び出されたメソッドを識別する java.lang.reflect.Method オブジェクト、および引数を格納する Object 型の配列をプロキシインスタンスに引き渡します。呼び出しハンドラは符号化されたメソッド呼び出しを適切に処理し、呼び出しハンドラが返す結果が、プロキシインスタンスでのメソッド呼び出しの結果として返されます。
プロキシクラスには以下のプロパティーがあります。
$Proxy」で始まるクラス名の領域をプロキシクラスのために確保しておく必要があります。
java.lang.reflect.Proxy を継承します。
Class オブジェクトで getInterfaces を呼び出すと、同じインタフェースのリストを生成時に指定された順序で格納する配列が返されます。Class オブジェクトで getMethods を呼び出すと、それらのインタフェースのメソッドすべてを含む Method オブジェクトの配列が返されます。getMethod を呼び出すと、予想されるメソッドがプロキシインタフェースで見つかります。
Proxy.isProxyClass メソッドは、プロキシクラス (Proxy.getProxyClass から返されたクラス、または Proxy.newProxyInstance から返されたオブジェクトのクラス) を渡された場合は true を返し、それ以外の場合は false を返します。
java.security.ProtectionDomain は、java.lang.Object などの、ブートストラップクラスローダによってロードされるシステムクラスの java.security.ProtectionDomain と同じです。プロキシクラスのコードは、信頼されたシステムコードによって生成されるためです。標準では、この保護ドメインに対して java.security.AllPermission が与えられます。
InvocationHandler の実装を取る 1 つの public コンストラクタがあります。プロキシインスタンスは、リフレクション API を介して public コンストラクタにアクセスしなくても、Proxy.newProxyInstance メソッドを呼び出すことによっても作成できます。このメソッドでは、Proxy.getProxyClass を呼び出すアクションと、呼び出しハンドラを使用してコンストラクタを呼び出すアクションが行われます。
プロキシインスタンスには以下のプロパティーがあります。
Foo がプロキシインスタンス proxy およびインタフェースの 1 つを実装している場合、次の式が true を返します。
proxy instanceof Foo
また、次のキャスト操作が成功します (ClassCastException をスローする場合を除く)。
(Foo) proxy
Proxy.getInvocationHandler メソッドは、その引数として渡されたプロキシインスタンスに関連付けられた呼び出しハンドラを返します。
invoke メソッドにディスパッチされます。
java.lang.Object に宣言されている hashCode、equals または toString の呼び出しは、前述したようにインタフェースメソッド呼び出しと同じ方法で、符号化され、呼び出しハンドラの invoke メソッドにディスパッチされます。invoke に渡される Method オブジェクトの宣言クラスは、java.lang.Object です。java.lang.Object から継承されるプロキシインスタンスのその他の public メソッドは、プロキシクラスによってオーバーライドされません。このため、これらのメソッドの呼び出しは、java.lang.Object のインスタンスに対する呼び出しと同様に行われます。
複数のインタフェースに、同じ名前とパラメータシグニチャーを持つメソッドが含まれる場合は、プロキシクラスのインタフェースの順番が区別されます。プロキシインスタンス上で重複するメソッドが呼び出された場合、呼び出しハンドラに渡される Method オブジェクトで、プロキシメソッドの呼び出しに使用されたインタフェースの参照型から宣言クラスを割り当てることができないことがあります。このような制約が存在するのは、生成されたプロキシクラス内の対応するメソッドの実装から、その実装が呼び出されたときに使用されたインタフェースを特定できないためです。このため、プロキシインスタンス上で重複するメソッドが呼び出された場合は、メソッド呼び出しに使用された参照型にかかわりなく、プロキシクラスのインタフェースリストでそのメソッド (直接またはスーパーインタフェースから継承) を含むインタフェースのうち、最初のインタフェースのメソッドの Method オブジェクトが呼び出しハンドラの invoke メソッドに渡されます。
プロキシインタフェースに、java.lang.Object の hashCode、equals、または toString メソッドと同じ名前およびパラメータシグニチャーを持つメソッドが含まれる場合は、プロキシインスタンス上でそのメソッドが呼び出されると、呼び出しハンドラに渡される Method オブジェクトの宣言クラスは java.lang.Object になります。つまり、public で非 final である java.lang.Object のメソッドは、呼び出しハンドラに渡す Method オブジェクトを決定するときに、論理的にほかのプロキシインタフェースより優先されます。
重複するメソッドが呼び出しハンドラにディスパッチされた場合は、invoke メソッドからスローできるチェック例外の型は、チェックされる型のうち、呼び出されるすべてのプロキシインタフェースのメソッドに指定されている、throws 句の例外の型に割り当てることができるものに限定されます。invoke メソッドが、呼び出しに使えるプロキシインタフェースの 1 つのメソッドで宣言された例外タイプのどれにも割り当てできないチェック例外をスローした場合、チェックされない UndeclaredThrowableException がプロキシインスタンスでの呼び出しによってスローされます。つまり、invoke メソッドに渡された Method オブジェクト上で、getExceptionTypes を呼び出して例外の型を取得しても、invoke メソッドから正常にスローされないことがあります。
InvocationHandler, 直列化された形式| 修飾子と型 | フィールドと説明 |
|---|---|
protected InvocationHandler |
h
このプロキシインスタンスの呼び出しハンドラです。
|
| 修飾子 | コンストラクタと説明 |
|---|---|
protected |
Proxy(InvocationHandler h)
指定された値で、サブクラス (通常は動的プロキシクラス) からその呼び出しハンドラに新しい
Proxy インスタンスを構築します。 |
| 修飾子と型 | メソッドと説明 |
|---|---|
static InvocationHandler |
getInvocationHandler(Object proxy)
指定されたプロキシインスタンスの呼び出しハンドラを返します。
|
static Class<?> |
getProxyClass(ClassLoader loader, Class<?>... interfaces)
クラスローダーとインタフェースの配列の指定されたプロキシクラスの
java.lang.Class オブジェクトを返します。 |
static boolean |
isProxyClass(Class<?> cl)
指定されたクラスが
getProxyClass メソッドまたは newProxyInstance メソッドを使って動的に生成されてプロキシクラスとなる場合にだけ、true を返します。 |
static Object |
newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
指定された呼び出しハンドラに対してメソッド呼び出しをディスパッチする、指定されたインタフェースのプロキシクラスのインスタンスを返します。
|
protected InvocationHandler h
protected Proxy(InvocationHandler h)
Proxy インスタンスを構築します。h - このプロキシインスタンスの呼び出しハンドラpublic static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces) throws IllegalArgumentException
java.lang.Class オブジェクトを返します。プロキシクラスは指定されたクラスローダーにより定義され、指定されたインタフェースをすべて実装します。インタフェースの同じ順列のプロキシクラスがすでにクラスローダーにより定義されている場合、既存のプロキシクラスが返されます。 そうでない場合は、これらのインタフェースのプロキシクラスが動的に生成され、クラスローダーにより定義されます。
Proxy.getProxyClass に引き渡されるパラメータには、いくつかの制約があります。
interfaces 配列の Class オブジェクトはすべて、クラスまたはプリミティブ型ではなくインタフェースを表す必要がある。
interfaces 配列の 2 つの要素が同一の Class オブジェクトを参照することはできない。
cl、各インタフェースが i の場合は、次の式が true でなければならない。
Class.forName(i.getName(), false, cl) == i
interfaces 配列のサイズは 65535 を超えてはならない。
これらの制約に対して違反が発生した場合は、Proxy.getProxyClass によって IllegalArgumentException がスローされます。interfaces 配列引数またはそのいずれかの要素が null の場合、NullPointerException がスローされます。
プロキシインタフェースは、順番が区別されます。プロキシクラスを 2 回要求したときに、インタフェースの組み合わせが同じで順番が異なる場合は、2 つの異なるプロキシクラスが作成されます。
loader - プロキシクラスを定義するクラスローダーinterfaces - プロキシクラスが実装するインタフェースのリストIllegalArgumentException - getProxyClass に引き渡されるパラメータに関する制約のどれかが守られなかった場合NullPointerException - interfaces 配列の引数またはその要素のいずれかが null の場合public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
Proxy.getProxyClass(loader, interfaces).
getConstructor(new Class[] { InvocationHandler.class }).
newInstance(new Object[] { handler });
Proxy.getProxyClass の場合と同じ理由で、Proxy.newProxyInstance は IllegalArgumentException をスローします。
loader - プロキシクラスを定義するクラスローダーinterfaces - プロキシクラスが実装するインタフェースのリストh - メソッド呼び出しのディスパッチ先の呼び出しハンドラIllegalArgumentException - getProxyClass に引き渡されるパラメータに関する制約のどれかが守られなかった場合NullPointerException - interfaces 配列の引数またはその要素のいずれかが null の場合、または呼び出しハンドラ h が null の場合public static boolean isProxyClass(Class<?> cl)
getProxyClass メソッドまたは newProxyInstance メソッドを使って動的に生成されてプロキシクラスとなる場合にだけ、true を返します。
セキュリティーを判定するときにこのメソッドを使用する場合は、信頼性が重要になります。このため、渡されたクラスが Proxy を継承しているかどうかを検査してから、追加の検査を行う必要があります。
cl - テストするクラスtrue、そうでない場合は falseNullPointerException - cl が null である場合public static InvocationHandler getInvocationHandler(Object proxy) throws IllegalArgumentException
proxy - 呼び出しハンドラを返すプロキシインスタンスIllegalArgumentException - 引数がプロキシインスタンスではない場合 バグまたは機能を送信
詳細な API リファレンスおよび開発者ドキュメントについては、Java SE のドキュメントを参照してください。そのドキュメントには、概念的な概要、用語の定義、回避方法、有効なコード例などの、開発者を対象にしたより詳細な説明が含まれています。
Copyright © 1993, 2013, Oracle and/or its affiliates. All rights reserved.