public class Proxy extends Object implements Serializable
Proxy
提供了创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类。
为某个接口创建代理Foo
:
InvocationHandler handler = new MyInvocationHandler(...);
Class<?> proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), Foo.class);
Foo f = (Foo) proxyClass.getConstructor(InvocationHandler.class).
newInstance(handler);
或更简单地:
Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
new Class<?>[] { Foo.class },
handler);
动态代理类 (以下简称为代理类 )是一个实现在类创建时在运行时指定的接口列表的类,具有如下所述的行为。 代理接口是由代理类实现的接口。 代理实例是代理类的一个实例。 每个代理实例都有一个关联的调用处理程序对象,它实现了接口InvocationHandler
。 通过其代理接口之一的代理实例上的方法调用将被分派到实例调用处理程序的invoke
方法,传递代理实例, java.lang.reflect.Method
被调用方法的java.lang.reflect.Method
对象以及包含参数的类型Object
Object的数组。 调用处理程序适当地处理编码方法调用,并且返回的结果将作为方法在代理实例上调用的结果返回。
代理类具有以下属性:
"$Proxy"
开头的类名空间应该保留给代理类。 java.lang.reflect.Proxy
。 getInterfaces
在其类
对象上调用getInterfaces
将返回一个包含相同列表接口的数组(按其创建时指定的顺序),在其类
对象上调用getMethods
将返回一个数组的方法
对象,其中包括这些接口中的所有方法,并调用getMethod
将在代理接口中找到可以预期的方法。 Proxy.isProxyClass
方法将返回true,如果它通过代理类 - 由Proxy.getProxyClass
返回的类或由Proxy.newProxyInstance
返回的对象的类 - 否则为false。 java.security.ProtectionDomain
代理类的是相同由引导类装载程序装载系统类,如java.lang.Object
,因为是由受信任的系统代码生成代理类的代码。 此保护域通常将被授予java.security.AllPermission
。 InvocationHandler
,设置调用处理程序的代理实例。 而不必使用反射API来访问公共构造函数,也可以通过调用Proxy.newProxyInstance
方法来创建代理实例,该方法将调用Proxy.getProxyClass
的操作与调用处理程序一起调用构造函数。 代理实例具有以下属性:
proxy
和其代理类Foo
,以下表达式将返回true: proxy instanceof Foo
并且以下演员操作将会成功(而不是投掷一个ClassCastException
): (Foo) proxy
Proxy.getInvocationHandler
方法将返回与作为其参数传递的代理实例关联的调用处理程序。 invoke
方法,如该方法的文档所述。 hashCode
, equals
在代理实例上的toString
中声明的java.lang.Object
或toString
或toString
或toString
方法将被编码并分派到调用处理程序的invoke
方法,方法与接口方法调用被编码和调度相同。 传递给invoke
的方法
对象的声明类将为java.lang.Object
。 从java.lang.Object
的代理实例的其他公共方法不会被代理类覆盖,因此这些方法的调用与java.lang.Object
。 当代理类的两个或多个接口包含具有相同名称和参数签名的方法时,代理类接口的顺序变得重要。 当在代理实例上调用这种重复方法时,传递给调用处理程序的方法
对象不一定是其声明类可以通过调用代理方法的接口的引用类型进行分配的对象。 存在此限制,因为生成的代理类中的相应方法实现无法确定其调用的接口。 因此,当在代理实例上调用重复的方法时,代理类的方法
列表中包含方法(直接或通过超级接口继承)的最重要的接口中的方法的Method对象被传递给调用处理程序的invoke
方法,而不管方法调用发生的引用类型。
如果代理接口包含具有相同的名称和参数签名的方法hashCode
, equals
,或toString
的方法java.lang.Object
,当这种方法在代理实例调用时, 方法
传递到调用处理程序对象将有java.lang.Object
为申报班 换句话说, java.lang.Object
的公共非最终方法java.lang.Object
上先于所有代理接口,以确定哪个方法
对象传递给调用处理程序。
还要注意,当将一个重复的方法分派到调用处理程序时, invoke
方法可能只会将可分配给所有可以调用的所有代理接口中的方法的throws
子句中的一种异常类型的检查异常类型抛出通过。 如果invoke
方法抛出经过检查的异常是不能分配给任何通过它可以通过调用代理接口中的方法声明的异常类型,那么选中UndeclaredThrowableException
将通过代理实例调用抛出。 此限制意味着,并非所有通过调用返回的异常类型getExceptionTypes
上方法
传递给对象invoke
方法一定可以成功地抛出invoke
方法。
InvocationHandler
, Serialized Form
Modifier and Type | Field and Description |
---|---|
protected InvocationHandler |
h
该代理实例的调用处理程序。
|
Modifier | Constructor and Description |
---|---|
protected |
Proxy(InvocationHandler h)
从一个子类(通常是一个动态代理类)构造一个新的
Proxy 实例,具有指定的调用处理程序的值。
|
Modifier and Type | Method and Description |
---|---|
static InvocationHandler |
getInvocationHandler(Object proxy)
返回指定代理实例的调用处理程序。
|
static 类<?> |
getProxyClass(ClassLoader loader, 类<?>... interfaces)
给出类加载器和接口数组的代理类的
java.lang.Class 对象。
|
static boolean |
isProxyClass(类<?> cl)
如果且仅当使用
getProxyClass 方法或
newProxyInstance 方法将指定的类动态生成为代理类时,则返回true。
|
static Object |
newProxyInstance(ClassLoader loader, 类<?>[] interfaces, InvocationHandler h)
返回指定接口的代理类的实例,该接口将方法调用分派给指定的调用处理程序。
|
protected InvocationHandler h
protected Proxy(InvocationHandler h)
Proxy
实例,该实例具有调用处理程序的指定值。
h
- 此代理实例的调用处理程序
NullPointerException
- 如果给定的调用处理程序
h
是
null
。
public static 类<?> getProxyClass(ClassLoader loader, 类<?>... interfaces) throws IllegalArgumentException
java.lang.Class
对象。
代理类将由指定的类加载器定义,并将实现所有提供的接口。
如果任何给定的接口是非公开的,则代理类将是非公开的。
如果类加载器已经定义了接口相同置换的代理类,那么将返回现有的代理类;
否则,这些接口的代理类将被动态生成并由类加载器定义。
对可能传递给Proxy.getProxyClass
的参数有几个Proxy.getProxyClass
:
interfaces
数组中的所有类
对象都必须表示接口,而不是类或原始类型。 interfaces
数组中没有两个元素可能是指相同的类
对象。 cl
和每个接口i
,以下表达式必须为真: Class.forName(i.getName(), false, cl) == i
interfaces
阵列的大小不得超过65535。 如果任何这些限制被违反, Proxy.getProxyClass
将抛出一个IllegalArgumentException
。 如果interfaces
数组参数或其任何元素为null
,则将抛出一个NullPointerException
。
请注意,指定的代理接口的顺序是重要的:具有相同组合的接口但不同顺序的代理类的两个请求将导致两个不同的代理类。
loader
- 类加载器来定义代理类
interfaces
- 要实现的代理类的接口列表
IllegalArgumentException
- 如果对可能传递给
getProxyClass
的参数的任何
getProxyClass
被违反
SecurityException
- 如果存在安全管理员s ,并且满足以下任何条件:
loader
是null
,并且调用者的类加载器不是null
,并且调用s.checkPermission
与RuntimePermission("getClassLoader")
权限被拒绝访问。 intf
,呼叫者的类加载器是不一样的或类加载器的一个祖先intf
和调用s.checkPackageAccess()
拒绝访问intf
。 NullPointerException
- 如果
interfaces
数组参数或其任何元素是
null
public static Object newProxyInstance(ClassLoader loader, 类<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
Proxy.newProxyInstance
因为与IllegalArgumentException
相同的原因而Proxy.getProxyClass
。
loader
- 类加载器来定义代理类
interfaces
- 代理类实现的接口列表
h
- 调度方法调用的调用处理函数
IllegalArgumentException
- 如果对可能传递给
getProxyClass
有任何
getProxyClass
被违反
SecurityException
-如果安全管理器,S存在任何下列条件得到满足:
loader
是null
,并且调用者的类加载器不是null
,并且调用s.checkPermission
与RuntimePermission("getClassLoader")
权限拒绝访问; intf
,呼叫者的类加载器是不一样的或类加载器的祖先intf
和调用s.checkPackageAccess()
拒绝访问intf
; s.checkPermission
与ReflectPermission("newProxyInPackage.{package name}")
权限拒绝访问。 NullPointerException
- 如果
interfaces
数组参数或其任何元素是
null
,或者如果调用处理程序
h
是
null
public static boolean isProxyClass(类<?> cl)
getProxyClass
方法或newProxyInstance
方法将指定的类动态生成为代理类时,则返回true。
这种方法的可靠性对于使用它来做出安全决策的能力很重要,所以它的实现不应该只是测试所讨论的类是否扩展了Proxy
。
cl
- 要测试的班级
true
如果该类是代理类,
false
false
NullPointerException
- 如果
cl
是
null
public static InvocationHandler getInvocationHandler(Object proxy) throws IllegalArgumentException
proxy
- 用于返回调用处理程序的代理实例
IllegalArgumentException
- 如果参数不是代理实例
SecurityException
-如果安全管理器
,S存在,并且调用者的类加载器是不一样或类加载器的调用处理程序和调用的祖先
s.checkPackageAccess()
拒绝访问到调用处理程序的类。