一 静态代理模式
在静态代理模式中有三类角色,理解了这三类角色也就理解了代理模式:
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());
}
}