Java 动态代理
代理是基本的设计模式之一,作用是为了提供额外的或不同的操作,而插入的用来代替“实际”对象的对象。这些操作通常涉及与“实际”对象的通信,因此代理通常充当着中间人的角色,下面是一个代理结构的例子:
先定义一个接口:
public interface Interface {
void doSomething();
void somethingElse(String arg);
}
class RealObject implements Interface{
@Override
public void doSomething() {
System.out.println("doSomething()");
}
@Override
public void somethingElse(String arg) {
System.out.println("somethingElse():" + arg);
}
}
再定义一个类来实现接口和重写该接口里的方法:
public class SimpleProxy implements Interface {
private Interface proxied;
public SimpleProxy(Interface proxied) {
this.proxied = proxied;
}
@Override
public void doSomething() {
System.out.println("SimpleProxy doSomething()");
proxied.doSomething();
}
@Override
public void somethingElse(String arg) {
System.out.println("SimpleProxy somethingElse():" + arg );
proxied.somethingElse(arg);
}
}
再定义一个方法来调用接口和类:
public class Demo {
public static void consumer(Interface iface) {
iface.doSomething();
iface.somethingElse("Hey");
}
public static void main(String[] args) {
consumer(new RealObject());
consumer(new SimpleProxy(new RealObject()));
}
}
输出结果:
因为consumer()接受的Interface,所以无法知道正在获得的到底是RealObject还是SimpleProxy,因为二者都是实现了Interface,但是SimpleProxy已经被插入到了客户端和RealObject之间,因此它会执行操作,然后调用了RealObject上相同的方法。
而Java的动态代理可以动态地创建代理并动态地处理对所代理方法的调用。在动态代理上所做的所有调用都会被重定向到单一的调用处理器上,揭示调用的类型并确定相应的对策,如动态代理重写Demo:
public class Dynamic implements InvocationHandler{
private Object proxied;
public Dynamic(Object proxied) {
this.proxied = proxied;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("proxy---" + proxy.getClass() + ",method---" + method + ",args---" + args);
if (args != null) {
for (Object object : args) {
System.out.println(" " + object);
}
}
return method.invoke(proxied, args);
}
}
public class Demo2 {
public static void consumer(Interface iface) {
iface.doSomething();
iface.somethingElse("Hey");
}
public static void main(String[] args) {
RealObject real = new RealObject();
consumer(real);
Interface proxy = (Interface)Proxy.newProxyInstance(
Interface.class.getClassLoader(),
new Class[] {Interface.class},
new Dynamic(real));
consumer(proxy);
}
}
输出结果:
通过调用静态方法Proxy.newProxyInstance()可以创建动态代理,这个方法需要得到一个类加载器,通常可以从已经被加载的对象中获取其类加载器,然后传递给它,该代理实现的接口列表(不是类或抽象类),以及InvocationHandler接口的一个实现。动态代理可以将所有调用重定向到调用处理器,因此通常会向调用处理器的构造器传递给一个“实际”对象的引用,从而使得调用处理器在执行其中介任务时,可以请求转发。