代理模式
在某些情况下,一个客户不想或者不能直接引用一个对象,此时可以通过一个称之为“代理”的第三者来实现间接引用。代理对象可以在客户端和目标对象之间起到 中介的作用,并且可以通过代理对象去掉客户不能看到 的内容和服务或者添加客户需要的额外服务。
简单来说代理模式就是通过一个代理对象去访问一个实际对象,并且可以像装饰模式一样给对象添加一些功能。
静态代理
所谓静态代理即在程序运行前代理类就已经存在,也就是说我们编写代码的时候就已经把代理类的代码写好了,而动态代理则是在程序运行时自动生成代理类。
描述起来太过抽象,看一下代码就明白是怎么回事了
· main
public class Main {
public static void main(String[] args) {
Water water = new Water();
WaterProxy waterProxy = new WaterProxy(water);
waterProxy.drink();
}
}
· 接口
//代理类与被代理类共同实现的接口
public interface Drink {
void drink();
}
· 被代理类
//被代理的类
public class Water implements Drink {
@Override
public void drink() {
System.out.println("drink water");
}
}
· 代理类
//代理类 //与被代理类实现同一个接口 public class DrinkProxy implements Drink { private Drink drinkImpl; //通过构造函数传入Water对象 public DrinkProxy(Drink drinkImpl) { this.drinkImpl = drinkImpl; } @Override public void drink() { //在执行被代理对象的方法前做一些事情 System.out.println("before drink"); //执行被代理对象的方法 drinkImpl.drink(); //在执行被代理对象的方法后做一些事 System.out.println("after drink"); } } |
执行结果
before drink
drink water
after drink
动态代理
有时候我们只想改变代理类所代理的类,但是代理对象执行实际对象的方法前后所做的事情是一样的,正所谓铁打的代理类,流水的被代理类。而采用静态代理就只能代理实现了同一接口的类,如果要代理任意类则必须写很多重复的代理类。此时我们可以采用动态代理,java已经为实现动态代理提供了一套比较方便的工具。
java.lang.reflect.Proxy类中可以动态生成代理对象的方法
/** *返回实现了指定接口的对象,调用代理对象的方法会调用 *InvocationHandler的invoke方法 * * @param loader 获取代理类所使用的类加载器 * @param interfaces 代理类所要实现的接口 * @param h 实现了InvocationHandler接口的对象 * @return 代理对象 */ public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h) |
InvocationHandler接口
/** *每个代理类都有一个关联的InvocationHandler *当代理对象执行一个方法的时候会直接执行invoke方法 */ public interface InvocationHandler { /** * @param 调用该方法的代理对象 * @param method 代理对象所调用的方法 * @param args 调用的方法的参数 * @return 调用的方法的返回值 */ public Object invoke(Object proxy, Method method, Object[] args) } |