|
JavaTM Platform Standard Ed. 6 |
|||||||||
| 前のクラス 次のクラス | フレームあり フレームなし | |||||||||
| 概要: 入れ子 | フィールド | コンストラクタ | メソッド | 詳細: フィールド | コンストラクタ | メソッド | |||||||||
java.lang.Objectjava.lang.reflect.Proxy
public class Proxy
Proxy は、動的プロキシのクラスおよびインスタンスを生成する静的メソッドを提供し、また、それらのメソッドによって生成された動的プロキシクラスすべてのスーパークラスでもあります。
インタフェース 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.newInstance メソッドを呼び出してプロキシインスタンスを生成することもできます。このメソッドは Proxy.getProxyClass の呼び出し動作を、呼び出しハンドラを持つコンストラクタの呼び出しと結合します。
プロキシインスタンスには、次の特性があります。
proxy プロキシインスタンス、およびその Foo プロキシクラスによって実装されたインタフェースに対して次の式を実行すると、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)
指定された呼び出しハンドラに対してメソッド呼び出しをディスパッチする、指定されたインタフェースのプロキシクラスのインスタンスを返します。 |
| クラス java.lang.Object から継承されたメソッド |
|---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
| フィールドの詳細 |
|---|
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 配列の複数の要素が、同じ 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.newProxyInstance は、Proxy.getProxyClass の場合と同じ理由で、IllegalArgumentException をスローします。
loader - プロキシクラスを定義するクラスローダーinterfaces - プロキシクラスが実装するインタフェースのリストh - メソッド呼び出しのディスパッチ先の呼び出しハンドラ
IllegalArgumentException - getProxyClass に引き渡されるパラメータに関する制約のどれかが守られなかった場合
NullPointerException - interfaces 配列の引数またはその要素のどれかが null の場合、または呼び出しハンドラ h が null の場合public static boolean isProxyClass(Class<?> cl)
getProxyClass メソッドまたは newProxyInstance メソッドを使って動的に生成されてプロキシクラスとなる場合にだけ、true を返します。
このメソッドの信頼性は、このメソッドによってセキュリティ保護をできるかどうかを決定する際に重要です。このため、当該クラスが Proxy を拡張するかどうかをこのメソッドの実装でテストするだけでは十分とは言えません。
cl - テストするクラス
true、そうでない場合は false
NullPointerException - cl が null の場合
public static InvocationHandler getInvocationHandler(Object proxy)
throws IllegalArgumentException
proxy - 呼び出しハンドラを返すプロキシインスタンス
IllegalArgumentException - 引数がプロキシインスタンスではない場合
|
JavaTM Platform Standard Ed. 6 |
|||||||||
| 前のクラス 次のクラス | フレームあり フレームなし | |||||||||
| 概要: 入れ子 | フィールド | コンストラクタ | メソッド | 詳細: フィールド | コンストラクタ | メソッド | |||||||||
Copyright 2009 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. Documentation Redistribution Policy も参照してください。