一 静态代理模式
在静态代理模式中有三类角色,理解了这三类角色也就理解了代理模式:
a.抽象对象:定义了真实角色和抽象角色的公共接口(可以是类,也可以是接口)Subject;
b.代理角色:代理角色内部包含有对真实角色的引用,通过这个引用去执行真实角色想要完成的任务;除此之外,代理角色可以完成其他的一些功能;
c.真实角色:实际要完成任务的角色,是我们始终要引用的对象。
代理角色和真实角色均实现了(或继承了)抽象角色。
写一段代码来举例:
//抽象角色,定义公共部分 interface Subject { public void request(); } //真实角色 class RealSubject implements Subject { public void request() { do something; } } //抽象角色,内部保存真实角色的引用 class ProxySubject implements Subject { private RealSubject sub; public ProxySubject(RealSubject obj) { this.sub = obj;//获得真实角色的实例引用 } public void request() { sub.request();//通过真实角色的引用去执行最终要完成的任务 } } public static void main(String[] args) { Subject proxy = new ProxySubject(); proxy.request(); }
二 动态代理模式
在学习动态代理模式时,学完了整个过程,我还是没有理解,下面的描述是我从自己理解的角度出发的,也许不适合别人阅读,也许会产生共鸣。
动态代理模式也是代理模式,所以它也会有三种角色。
抽象角色,定义公共部分,interface Subject;
真实角色,完成实际的工作,class RealSubject implements Subject。
class DynamicSubject:里面保存真实角色的引用,实现了InvocationHandler接口,InvocationHandler接口中有一个invoke方法,接受三个参数:
一个是代理实例;
一个是要执行方法的Method对象,通过调用Method对象的invoke()方法,便可以执行该方法了;
一个是执行该方法所需要的参数。
在使用动态代理模式时,首先需要得到真实角色的一个实例:RealSubject real = new RealSubject();
DynamicSubject实现了InvocationHandler接口,DynamicSubject里保存了一个真实角色的引用sub,通过构造方法来得到它:InvocationHandler handler = new DyanmicSubject(real);
接下来就是通过Proxy动态的生成一个动态代理类(也就是代理模式中的代理角色),分析一下,如果要生一个代理类需要哪些条件?根据静态代理来分析:
(1)要实现Subject接口,谁实现了Subject接口?RealSubject!所以需要RealSubject实现的接口的列表:RealSubject.class.getInterfaces()。
(2)要实现Subject中的方法。但是动态代理把执行方法的任务交给了InvocationHandler,所以需要一个InvocationHandler的对象。
Proxy动态生成了该代理类后,返回一个该类的实例。想一想,代理模式的前提是什么?是有一个定义了公共部分的接口Subject,由Subject的一个实例去调用要执行的方法。生成的动态代理类实现了哪个接口?Subject!所以返回的该动态代理类的实例必定是Subject类型的:
Subject sub = (Subject)动态代理类实例;
sub.调用要执行的方法;
回想一下:动态代理模式把执行方法的任务交给了InvocationHandler,所以sub.调用要执行的方法这一步实际上是把执行动作转移到了handler上了,调用了handler的invoke方法。handler的invoke方法再去调用实际要执行方法的Method对象的invoke()方法。
以上的描述可能比较乱,总结一下:
(1)动态代理模式,也需要三种角色:抽象角色Subject;真实角色RealSubject;代理角色,由Proxy动态生成。
(2)动态代理模式把执行方法的任务交给了InvocationHandler,所以需要一个类去实现InvocationHandler接口,并且实现invoke方法。
(3)生成动态代理类需要三个条件:类加载器;真实角色实现的接口列表;handler。需要handler的原因是因为:方法最终是在handler的invoke()方法中执行;在生成动态代理类的实例时,完成代理类和handler的关联。
//抽象角色 public interface Subject { public void request(); } //真实角色 public class RealSubject implements Subject { @Override public void request() { System.out.println("From real Subject"); } } //InvocationHandler import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; /* * 该代理类内部的属性是Object类型,实际使用的时候通过构造方法传递进来一个对象sub * 此外,该类还实现了invoke方法,该方法中的method.invoke其实就是调用被代理对象将要执行的方法, * 方法参数是sub,表示该方法从属于sub * */ public class DynamicSubject implements InvocationHandler { private Object sub; public DynamicSubject(Object obj) { this.sub = obj; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before : " + method); System.out.println("method name : " + method.getName() + "," + args); method.invoke(sub, args); System.out.println("after : " + method); return null; } } public class Client { /** * @param args */ public static void main(String[] args) { RealSubject realSubject = new RealSubject(); InvocationHandler handler = new DynamicSubject(realSubject); Class<?> clazz = handler.getClass(); //下面的代码一次性生成代理 //完成两件事:动态生成一个代理类,并且生成这个类的一个实例 Subject subject = (Subject) Proxy.newProxyInstance(clazz.getClassLoader(), RealSubject.class.getInterfaces(), handler); subject.request();//实际上将是将方法的执行转移到了handler上了,调用handler.invoke()方法 System.out.println(subject.getClass()); } }