8,代理模式
一,概念
Proxy模式又叫做代理模式,是构造型的设计模式之一,它可以为其他对象提供一种代理(Proxy)以控制对这个对象的访问。
所谓代理,是指具有与代理元(被代理的对象)具有相同的接口的类,客户端必须通过代理与被代理的目标类交互,而代理一般在交互的过程中(交互前后),进行某些特别的处理。
二,例子
三个要素
抽象主题角色(subject):真实主题与代理主题的共同接口。
具体主题角色(RealSubject):定义了代理角色所代表的真实对象。
代理主题角色(Proxy):含有对真实主题角色的引用,代理角色通常在将客户端调用传递给真是主题对象之前或者之后执行某些操作,而不是单纯返回真实的对象。
例子:
抽象主题角色(subject):Subject
/** * * @类名称:Subject * @类描述:抽象主题角色(subject) * @创建人:zender */ public interface Subject { public void sailBook(); }
具体主题角色(RealSubject):RealSubject
/** * * @类名称:RealSubject * @类描述:具体主题角色(RealSubject) * @创建人:zender */ public class RealSubject implements Subject { @Override public void sailBook() { System.out.println("卖书"); } }
代理主题角色(Proxy):ProxySubject
/** * * @类名称:ProxySubject * @类描述:代理主题角色(Proxy) * @创建人:zender */ public class ProxySubject implements Subject{ private RealSubject realSubject; @Override public void sailBook() { dazhe(); if(realSubject == null) { realSubject = new RealSubject(); } realSubject.sailBook(); give(); } public void dazhe() { System.out.println("打折8折。"); } public void give() { System.out.println("赠送50元代金券。"); } }
测试:
/** * * @类名称:Test * @类描述:测试 * @创建人:zender */ public class Test { public static void main(String[] args) { ProxySubject ps = new ProxySubject(); ps.sailBook(); } }
结果:
三,动态代理
在使用动态代理时,我们需要定义一个位于代理类与委托类之间的中介类,这个中介类被要求实现InvocationHandler接口。
从InvocationHandler这个名称我们就可以知道,实现了这个接口的中介类用做"调用处理器"。当我们调用代理类对象的方法时,这个"调用"会转送到invoke方法中,代理类对象作为proxy参数传入,参数method标识了我们具体调用的是代理类的哪个方法,args为这个方法的参数。这样一来,我们对代理类中的所有方法的调用都会变为对invoke的调用,这样我们可以在invoke方法中添加统一的处理逻辑(也可以根据method参数对不同的代理类方法做不同的处理)。
例子:
抽象主题角色(subject):Subject
/** * * @类名称:Subject * @类描述:抽象主题角色(subject) * @创建人:zender */ public interface Subject { public void sailBook(); }
具体主题角色(RealSubject):RealSubject
/** * * @类名称:RealSubject * @类描述:具体主题角色(RealSubject) * @创建人:zender */ public class RealSubject implements Subject { @Override public void sailBook() { System.out.println("卖书"); } }
中介类:MyHandler
/** * * @类名称:MyHandler * @类描述:中介类 * @创建人:zender */ public class MyHandler implements InvocationHandler { private RealSubject realSubject; public void setRealSubject(RealSubject realSubject) { this.realSubject = realSubject; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; dazhe(); try { result = method.invoke(realSubject, args); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } give(); return result; } public void dazhe() { System.out.println("打折8折。"); } public void give() { System.out.println("赠送50元代金券。"); } }
测试:
/** * * @类名称:Test * @类描述:测试 * @创建人:zender */ public class Test { public static void main(String[] args) { RealSubject realSubject = new RealSubject(); MyHandler myHandler = new MyHandler(); myHandler.setRealSubject(realSubject); Subject proxySubject = (Subject)Proxy.newProxyInstance(RealSubject.class.getClassLoader(), realSubject.getClass().getInterfaces(), myHandler); proxySubject.sailBook(); } }
结果:
四,Cglib动态代理
JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
需要下载jar:cglib-2.2.2.jar,asm-3.3.1.jar
例子:
抽象主题角色(subject):Subject
/** * * @类名称:Subject * @类描述:抽象主题角色(subject) * @创建人:zender */ public interface Subject { public void sailBook(); }
具体主题角色(RealSubject):RealSubject
/** * * @类名称:RealSubject * @类描述:具体主题角色(RealSubject) * @创建人:zender */ public class RealSubject implements Subject { @Override public void sailBook() { System.out.println("卖书"); } }
代理类:MyInterceptor
/** * * @类名称:MyInterceptor * @类描述:代理类 * @创建人:zender */ public class MyInterceptor implements MethodInterceptor{ //创建代理对象 public Object getProxy(Class clazz) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(clazz); // 回调方法 enhancer.setCallback(this); // 创建代理对象 return enhancer.create(); } @Override public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable { dazhe(); Object o = arg3.invokeSuper(arg0, arg2); give(); return o; } public void dazhe() { System.out.println("打折8折。"); } public void give() { System.out.println("赠送50元代金券。"); } }
测试:
/** * * @类名称:Test * @类描述:测试 * @创建人:zender */ public class Test { public static void main(String[] args) { MyInterceptor mi = new MyInterceptor(); RealSubject rs = (RealSubject) mi.getProxy(RealSubject.class); rs.sailBook(); } }
结果: