|
JavaTM 2 Platform Std. Ed. v1.3 |
|||||||||
| 前のクラス 次のクラス | フレームあり フレームなし | |||||||||
| 概要: 内部クラス | フィールド | コンストラクタ | メソッド | 詳細: フィールド | コンストラクタ | メソッド | |||||||||
java.lang.Object | +--java.lang.reflect.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 の呼び出し動作を、呼び出しハンドラを持つコンストラクタの呼び出しと結合します。
プロキシインスタンスには以下のプロパティがあります。
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 のインスタンスを呼び出すのと同じような動作をします。
プロキシクラスの 2 つ以上のインタフェースが同じ名前とパラメータシグニチャーを持つメソッドを含む場合、プロキシクラスのインタフェースの順序が重要になります。プロキシインスタンスでこのような重複メソッドが呼び出された場合、呼び出しハンドラに引き渡された Method オブジェクトは必ずしも、プロキシのメソッドの呼び出しに使われたインタフェースの参照型から宣言クラスを割り当てできるオブジェクトである必要はありません。この制限があるのは、生成されたプロキシクラスの該当のメソッド実装が、呼び出しに使われたインタフェースを判定できないためです。したがって、重複メソッドがプロキシインスタンスで呼び出された場合、メソッド呼び出しが発生した参照型にかかわらず、プロキシクラスのインタフェースのリストのメソッドを直接に、またはスーパーインタフェース経由で継承して含む主要なインタフェースのメソッドの Method オブジェクトが、呼び出しハンドラの invoke メソッドに引き渡されます。
プロキシインタフェースが java.lang.Object の hashCode、equals、または toString の各メソッドと同じ名前とパラメータシグニチャーを持っているメソッドを含む場合、プロキシインスタンスでこのようなメソッドが呼び出されると、呼び出しハンドラに引き渡された Method オブジェクトはその宣言クラスとして java.lang.Object を持ちます。言い換えると、java.lang.Object の、public であり final でないメソッドは、呼び出しハンドラにどの Method オブジェクトを引き渡すかを決定する際に、プロキシインタフェースのすべてに論理的に優先します。
重複メソッドが呼び出しハンドラにディスパッチされる場合、invoke メソッドは、呼び出しに使用できるすべてのプロキシインタフェースのメソッドの throws 節の例外タイプの 1 つに割り当て可能な確認済み例外タイプだけをスローできます。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 配列の 2 つの要素が同一の Class オブジェクトを参照することはできない
cl および全インタフェース i について、以下の式が true でなければならない
Class.forName(i.getName(), false, cl) == i
interfaces 配列のサイズは 65535 を超えてはならない
これらの制約に 1 つでも違反する場合は、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 - 引数がプロキシインスタンスではない場合
|
JavaTM 2 Platform Std. Ed. v1.3 |
|||||||||
| 前のクラス 次のクラス | フレームあり フレームなし | |||||||||
| 概要: 内部クラス | フィールド | コンストラクタ | メソッド | 詳細: フィールド | コンストラクタ | メソッド | |||||||||
Java、Java 2D、JDBC は、米国およびその他の国における米国 Sun Microsystems, Inc. の商標もしくは登録商標です。
Copyright 1993-2000 Sun Microsystems, Inc. 901 San Antonio Road,
Palo Alto, California, 94303, U.S.A. All Rights Reserved.