Java的代理模式
什么是代理模式[Proxy Pattern]?
代理模式就是为了在其他对象访问一个对象时,提供一种代理,而不是直接访问该对象。
有点像在外部进行了一层包裹。
这个代理模式,和装饰器模式Decorator Pattern的区别在于proxy是为了控制,decorator是为了增强功能。
静态代理和动态代理
-
静态代理类就是类已经生成好了,而不是在程序运行时生成的。
静态一旦写完,一般就代理一个固定的类。 -
动态代理类在很多场景下在client和target之间充当一个中介者的角色。动态代理类时在运行时生成字节码,
接口
/**
* Interface IVehicle.
*/
public interface IVehicle {
public void start();
public void stop();
public void forward();
public void reverse();
public String getName();
}
target class
/**
* Class Car
*/
public class Car implements IVehicle {
private String name;
public Car(String name) {this.name = name;}
public void start() {
System.out.println("Car " + name + " started");
}
// stop(), forward(), reverse() implemented similarly.
// getName() not shown.
}
client
/**
* Class Client1.
* Interacts with a Car Vehicle directly.
*/
public class Client1 {
public static void main(String[] args) {
IVehicle v = new Car("Botar");
v.start();
v.forward();
v.stop();
}
}
代理类
/**
* Class VehicleProxy.
*/
public class VehicleProxy implements IVehicle {
private IVehicle v;
public VehicleProxy(IVehicle v) {this.v = v;}
public void start() {
System.out.println("VehicleProxy: Begin of start()");
v.start();
System.out.println("VehicleProxy: End of start()");
}
// stop(), forward(), reverse() implemented similarly.
// getName() not shown.
}
代理类的client2
/**
* Class Client2.
* Interacts with a Car Vehicle through a VehicleProxy.
*/
public class Client2 {
public static void main(String[] args) {
IVehicle c = new Car("Botar");
IVehicle v = new VehicleProxy(c);
v.start();
v.forward();
v.stop();
}
}
动态代理
- 动态代理是在运行时实现了目标类的一系列接口
- 代理instance是代理类的一个instance
- 每一个代理实例都会调用一个实现InvoicationHandler接口的handler object
- 代理实例上的方法调用通过他的代理接口调用实例的invocation handler
- 代理类的创建是通过 java.lang.reflect.Proxy
- 代理类的名字是以
$Proxy
开头 - 当代理类创建的时候, 所指定的接口会被实现。
- 当代理类创建时实现了所有接口, 代理类调用
getInterfaces()
会返回一个包含所有接口的接口数组。 - 每一个代理类有一个public的构造函数 需要一个实现
InvocationHandler
接口的handler 作为参数。
getProxyClass
public static Class getProxyClass(ClassLoader loader,
Class[] interfaces)
throws IllegalArgumentException
通过类加载器,接口数组,返回一个代理类。
Proxy
构造一个Proxy 实例
protected Proxy(InvocationHandler ih)
isProxyClass
判断是否一个代理类。
public static boolean isProxyClass(Class c)
newProxyInstance
public static Object newProxyInstance(ClassLoader loader,
Class[] interfaces,
InvocationHandler ih)
throws IllegalArgumentException
以下2个写法是等价的
Proxy.newProxyInstance(cl, interfaces, ih);
Proxy.getProxyClass(cl,
interfaces).getConstructor(new Class[] {
InvocationHandler.class }).newInstance(new
Object[] {ih});
getInvocationHandler
从指定的proxy 返回一个调用invocation handler
public static InvocationHandler getInvocationHandler
(Object proxy)
throws IllegalArgumentException
invoke
处理代理实例上的方法调用并且返回object
proxy是代理类,method是方法名,args是方法对应的参数
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable
所以这样一来,handler就是这样
/**
* Class VehicleHandler.
*/
public class VehicleHandler implements InvocationHandler {
private IVehicle v;
public VehicleHandler(IVehicle v) {this.v = v;}
public Object invoke(Object proxy, Method m, Object[] args)
throws Throwable {
System.out.println("Vehicle Handler: Invoking " +
m.getName());
return m.invoke(v, args);
}
}
代理类的 client3
/**
* Class Client3.
* Interacts with a Car Vehicle through a dynamically
* generated VehicleProxy.
*/
public class Client3 {
public static void main(String[] args) {
IVehicle c = new Car("Botar");
ClassLoader cl = IVehicle.class.getClassLoader();
IVehicle v = (IVehicle) Proxy.newProxyInstance(cl,
new Class[] {IVehicle.class}, new VehicleHandler(c));
v.start();
v.forward();
v.stop();
}
}