代理模式是一种应用非常广泛的设计模式,当客户端代码需要调用某个对象的时候,客户端并不关心是否可以准确的得到这个对象,他只要一个能够提供该功能的对象而已,此时我们就可以返回该对象的代理。总而言之,客户端代码不能或者不想直接访问被调用对象,服务器这段额外的建立一个代理对象返回给客户端使用,那么这种设计方式就是代理模式。
自从JDK的版本到1.3以后,java语言通过java.lang.reflect库中,提供了三个类来直接支持代理模式。分别是:Proxy,InvocoationHandler和Method。Proxy类使得设计师能够在运行时间创建代理对象,当系统有了一个代理对象后,对源对象的方法调用会首先被分派给一个调用处理器(InvocationHandler)//接口,InvocationHandler接口中有一个invoke()方法,程序可以在调用处理器的invoke方法中截获这个调用,进行额外的操作。
创建动态代理对象的步骤:
1.指明一系列的接口来创建一个代理对象
2.创建一个调用处理器(InvocationHandler)对象
3.将这个代理指定为某个其他对象的代理对象
4.在调用处理器的invoke方法中采取代理,一方面将调用传递给真实对象,另一方面执行各种需要做的操作。
其中代理模式在hibernate和spring中都有应用,下面代码模拟hibernate中的懒加载。
代码如下:
<strong><span style="font-size:14px;">//代理和实际对象都要实现的接口 interface Image{ //随便定义一个方法 public void show(); } //模拟客户端使用的代理 class ImageProxy implements Image{ private Image image; public ImageProxy(Image image) { super(); this.image = image; } @Override public void show() { //加入自己的代码逻辑 在用到这个show方法的时候 才会去真正的创建那个实实在在的对象 if(null == image){ image = new BigImage(); } image.show(); } } //实际的对象 public class BigImage implements Image{ public BigImage(){ try { Thread.sleep(5000); System.out.println("BigImage..."); } catch (InterruptedException e) { e.printStackTrace(); } } @Override public void show() { System.out.println("梦似烟花心似水,同学少年不言情。。。"); } public static void main(String[] args) { //直接使用真正的对象 在new那个对象的时候会有的5000秒的延迟 long stateTime1 = System.currentTimeMillis(); Image image1 = new BigImage(); System.out.println(System.currentTimeMillis() - stateTime1+"\n"); //使用代理,直接很快的创建了一个代理对象,在真正使用到对象的show方法的时候 才会有5000秒的延迟 long stateTime = System.currentTimeMillis(); Image image = new ImageProxy(null); System.out.println(System.currentTimeMillis() - stateTime); image.show(); } } </span></strong>
在spring中也使用了代理模式,其中spring的AOP就是代理模式的一个典型应用。
<strong><span style="font-size:14px;">import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; //java动态代理 代理对象和被代理对象都要实现的接口 interface Dog{ public void info(); public void run(); } //模拟事务管理器 class TxUtil{ public void beginTx(){ System.out.println("...模拟事务开始..."); } public void endTx(){ System.out.println("...模拟事务结束...\n"); } } //java动态代理的关键之一,InvocationHandler的实现类,这个类的invoke方法将成为最后代理对象方法的实现 class LinkinInvocationHandler implements InvocationHandler{ //需要被代理的对象 private Object target; public void setTarget(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { TxUtil txUtil = new TxUtil(); txUtil.beginTx(); //方法的反射 需要被代理的对象作为主调来调用方法 Object result = method.invoke(target, args); txUtil.endTx(); return result; } } //模拟一个获得代理对象的工厂 class LinkinProxyFactory{ public static Object getProxyInstance(Object target){ LinkinInvocationHandler hander = new LinkinInvocationHandler(); hander.setTarget(target); //改天复习下反射 注意下面方法的返回值 return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), hander); } } //被代理对象 public class MyDog implements Dog{ @Override public void info() { System.out.println("忠犬8公..."); } @Override public void run() { System.out.println("很忠诚的..."); } public static void main(String[] args) { //获得一个被代理对象 MyDog myDog = new MyDog(); //以被代理对象作为参数获得一个代理对象 一般情况下编译类型都是接口 Dog myDogProxy = (Dog) LinkinProxyFactory.getProxyInstance(myDog); myDogProxy.info(); myDogProxy.run(); } }</span></strong>