以下内容翻译自不知名的某个文档
作为client和target之间的中间人(intermediary),代理在很多场合下是很有用的。
为了进一步理解动态代理的作用,我们首先看一个不使用代理机制的实例。
public interface IVehicle { public void start(); public void stop(); public String getName(); }
public class Car implements IVehicle { String name; public Car(String name) { this.name = name; } public void start() { System.out.println("start(): The car" + name + " started"); } public void stop() { System.out.println("stop(): The car" + name + " stopped"); } public String getName() { return this.name; } }
public class Client { public static void main(String[] args) { IVehicle v = new Car("BMW"); v.start(); v.stop(); } }运行结果为
start(): The carBMW started stop(): The carBMW stopped
本例子的调用关系图为
记住:使用代理的主要目的是为了更好地控制对target的访问,而不是增强target的功能(functionality)。
代理通过以下方式来实现对target的访问控制:
public class VehicleProxy implements IVehicle { private IVehicle v; public VehicleProxy(IVehicle v) { this.v = v; } public void start() { System.out.println("VehicleProxy.start()"); v.start(); } public void stop() { System.out.println("VehicleProxy.stop()"); v.stop(); } public String getName() { System.out.println("VehicleProxy.getName()"); return v.getName(); } }
public class Client2 { public static void main(String[] args) { IVehicle car = new Car("BMW"); IVehicle v = new VehicleProxy(car); v.start(); v.stop(); } }运行结果为
VehicleProxy.start() start(): The carBMW started VehicleProxy.stop() stop(): The carBMW stopped
以上这个是用代理的例子似乎也达到了我们的目的,现在,我们希望在调用Car的每一个方法的之前和之后,都能打印出一些日志信息,例如传入的参数和输出的结果。但是我们也要考虑到以下事实:
好了,是该看看动态代理的时候了
Proxy类为创建动态代理类和动态代理实例提供的静态方法,同时它也是由这些静态方法创建的动态代理类的父类。
为接口Foo创建动态代理类:
InvocationHandler handler = new MyInvocationHandler(...); Class proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), new class[]{foo.class}); Foo foo = proxyClass.getConstructor(new class[]{InvocationHandler.class}).newInstance(new Object[]{handler});
InvocationHandler handler = new MyInvocationHandler(...); Foo foo = Proxy.newProxyInstance(Foo.class.getClassLoader(), new Class[]{Foo.class}, handler);
我们将前面的例子用动态代理的方式来做如下改造
public interface IVehicle { public void start(); public void stop(); public String getName(); }
public class Car implements IVehicle { String name; public Car(String name) { this.name = name; } @Override public void start() { System.out.println("start(): The car " + name + " started"); } @Override public void stop() { System.out.println("stop(): The car " + name + " stopped"); } @Override public String getName() { System.out.println("getName(): The car " + name + "'s name is retrieved"); return this.name; } }
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.util.Arrays; public class VehicleHandler implements InvocationHandler { private IVehicle target; public VehicleHandler(IVehicle target) { this.target = target; } @Override public Object invoke(Object proxy, Method m, Object[] args) throws Throwable { System.out.println("[Before Method Call] The method " + m.getName() + "() begins with " + Arrays.toString(args)); Object result = m.invoke(target, args); System.out.println("[After Method Call] The method " + m.getName() + "() ends with " + result); return result; } }
import java.lang.reflect.Proxy; public class Client { public static void main(String[] args) { IVehicle car = new Car("Ford"); IVehicle proxiedCar = (IVehicle) Proxy.newProxyInstance( car.getClass().getClassLoader(), car.getClass().getInterfaces(), new VehicleHandler(car)); proxiedCar.start(); System.out.println("-------------------------------------------"); String name = proxiedCar.getName(); } }
运行结果为
[Before Method Call] The method start() begins with null start(): The car Ford started [After Method Call] The method start() ends with null ------------------------------------------- [Before Method Call] The method getName() begins with null getName(): The car Ford's name is retrieved [After Method Call] The method getName() ends with Ford