在阎宏博士的《JAVA与模式》一书中开头是这样描述代理(Proxy)模式的:代理模式是对象的结构模式。代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。
代理模式的结构
代理对象在客户端和目标对象之间起到中介的作用。
代理模式类图如下:
代理模式中的角色:
抽象对象角色:声明了目标对象和代理对象的共同接口,在使用目标对象的地方都可以使用代理对象。
目标对象角色:定义了代理对象代表的目标对象。
代理对象角色:代理对象内部有目标对象的引用,可以操作目标对象。
抽象对象角色:
1 public abstract class AbstractObject {
2 //操作
3 public abstract void operation();
4 }
目标对象角色:
1 public class RealObject extends AbstractObject {
2 @Override
3 public void operation() {
4 //一些操作
5 System.out.println("一些操作");
6 }
7 }
代理对象角色:
1 public class ProxyObject extends AbstractObject{
2 RealObject realObject = new RealObject();
3 @Override
4 public void operation() {
5 //调用目标对象之前可以做相关操作
6 System.out.println("before");
7 realObject.operation();
8 //调用目标对象之后可以做相关操作
9 System.out.println("after");
10 }
11 }
客户端:
1 public class Client {
2
3 public static void main(String[] args) {
4 // TODO Auto-generated method stub
5 AbstractObject obj = new ProxyObject();
6 obj.operation();
7 }
8
9 }
代理对象在调用目标对象的方法调用前后进行预处理和相关的后置处理。这种代理模式也被称为“静态代理模式”,因为在编译阶段要为每个RealObject类创建一个ProxyObject类,当需要代理的类很多时,就会出现大量的ProxyObject类。可以使用动态代理来解决这个问题。
动态代理的实现方式有JDK动态代理和CGLIB动态代理,目标对象是代理类的一个属性,代理类可以在调用目标对象方法前后加上处理逻辑。两者区别如下:
1 JDK动态代理基于接口,代理类和目标类实现了相同的接口,而CGLIB(CODE GENERLIZE LIBRARY)动态代理基于类,子类继承指定的类,覆盖父类方法,不能代理final修饰的类和覆盖final修饰的方法。
2 CGLIB底层采用ASM字节码生成框架,使用字节码技术生成代理类,理论上比使用Java反射效率要高。但是根据JDK动态代理与CGLIB动态代理的一万次执行代码实验,JDK7及8的动态代理速度比CGLIB快20%左右。
参考资料
《MyBatis技术内幕》