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
、そうでない場合は false
NullPointerException
- 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.