|
JavaTM 2 Platform Standard Ed. 5.0 |
|||||||||
前のクラス 次のクラス | フレームあり フレームなし | |||||||||
概要: 入れ子 | フィールド | コンストラクタ | メソッド | 詳細: フィールド | コンストラクタ | メソッド |
java.lang.Object java.lang.reflect.Proxy
public class Proxy
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.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
、そうでない場合は false
NullPointerException
- cl
が null
の場合public static InvocationHandler getInvocationHandler(Object proxy) throws IllegalArgumentException
proxy
- 呼び出しハンドラを返すプロキシインスタンス
IllegalArgumentException
- 引数がプロキシインスタンスではない場合
|
JavaTM 2 Platform Standard Ed. 5.0 |
|||||||||
前のクラス 次のクラス | フレームあり フレームなし | |||||||||
概要: 入れ子 | フィールド | コンストラクタ | メソッド | 詳細: フィールド | コンストラクタ | メソッド |
Copyright 2004 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. Documentation Redistribution Policy も参照してください。