# Java中的代理类
public class Proxy extends Object implements Serializable
Proxy类提供了用于创建动态代理类和实例的静态方法,它同时也是这些方法所创建的实例的超类。
要创建某个接口Foo的代理:
InvocationHandler handler = new MyInvocationHandler();
Class<?> proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(),Foo.class);
Foo f = proxyClass.getConstructor(InvocationHandler.class).newInstance(handler);
// 更简单的方式
Foo f = (Foo)Proxy.newProxyInstance(Foo.class.getClassLoader(),new Class<?>[]{Foo.class},handler);
一个动态代理类(下面简称为代理类)是这样一个类:它在创建时,实现了在运行时指定的一系列接口。一个代理接口是一个被代理类实现的接口。一个代理实例就是代理类的实例。每一个代理实例都有一个关联的调用处理器对象(invocation handler),该对象实现了InvocationHandler
接口。在该代理对象上调用一个代理接口的方法时,会被分发到该实例的调用处理器的invoke方法上,同时传给该方法的还有代理实例,一个java.lang.reflect.Method
对象,该对象决定要调用的方法,以及一个对象数组包含调用参数。调用处理器会适当的处理被编码的方法,并且该方法的返回值会作为该代理实例在该方法调用上的结果被返回。
一个代理类有如下属性:
- 如果所有的代理接口都是public,那么代理类就是 public,final以及非abstract
- 如果任何代理接口是非public的,代理类就是非public的
- 代理类的非限定名是未指定的。类名中"$Proxy"部分应该是,然而,这为代理类保留了。
- 一个代理类继承自
java.lang.reflect.Proxy
- 一个代理类准确的按顺序实现了创建时的指定的接口
- 如果一个代理类实现了一个非public接口,那么它需要和那个接口定义在同一个包内。否则,代理类的包名是不确定的,既不是同一个类加载器定义的类也不是具有特定签名的相同包。
- 因为一个代理类创建时实现了所有指定接口,在该类对象上调用
getInterfaces
会返回相同的接口列表数组,调用getMethod
,会返回一个Method对象的数组,该数组包含那些接口的所有方法。 - 如果一个类是通过
Proxy.getProxyClass
,或该类通过Proxy.newProxyInstance
的结果对象得到的,那么Proxy.isProxyClass
方法会返回真。 - 未翻译
- 每一个代理类都有一个接收一个参数的构造器,接收的参数为接口
InvocationHandler
的实现,来为代理对象设置一个调用处理器。除了通过反射拿到公共的构造器,一个代理实例也可以通过Proxy.newProxyInstance
方法来创建,该方法组合了Proxy.getProxyClass
以及使用调用处理器构造该对象的步骤。
示例代码:
package reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import static java.lang.System.out;
/**
* Created by jintaox on 2017/3/14.
*/
public class UseProxy {
public static void main(String[] args) {
Class clazzFoo = Proxy.getProxyClass(Foo.class.getClassLoader(), new Class[]{Foo.class});
try {
Constructor clazzFooConstructor = clazzFoo.getConstructor(new Class[]{InvocationHandler.class});
Foo fooProxy = (Foo) clazzFooConstructor.newInstance(new Object[]{new MyInvocationHandler(new FooI())});
fooProxy.work("hello world");
out.format("isProxyClass?\t%s\n", Proxy.isProxyClass(clazzFoo));
out.format("getInvocationHandler:\t%s\n", Proxy.getInvocationHandler(fooProxy));
out.format("newProxyInstance...\n");
Foo fooProxy1 = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), new Class[]{Foo.class}, new MyInvocationHandler(new FooI()));
fooProxy1.work("this way");
} catch (Exception e) {
e.printStackTrace();
}
}
}
class MyInvocationHandler implements InvocationHandler {
private Object targetObj;
public MyInvocationHandler(Object targetObj) {
this.targetObj = targetObj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("what proxy is?"+proxy.getClass().getSimpleName());
System.out.println("before invoke...");
Object result = method.invoke(targetObj, args);
System.out.println("after invode...");
return result;
}
@Override
public String toString() {
return "MyInvocationHandler{" +
"targetObj=" + targetObj +
'}';
}
}
interface Foo {
String work(String msg);
}
class FooI implements Foo {
@Override
public String work(String msg) {
System.out.println("working..." + msg);
return "haha" + msg;
}
}