基本概念
代理模式(Proxy):为其他对象提供一种代理,并控制该对象的访问(Provide asurrogate or placeholder foranother object to control access to it. )。而对一个对象进行访问控制的一个原因是为了只有在我们确实需要这个对象时才对它进行创建和初始化。它是给某一个对象提供一个替代者(占位者),使之在client对象和subject对象之间编码更有效率。代理可以提供延迟实例化(lazy instantiation),控制访问等。
三种角色:
- 抽象角色:声明真实对象和代理对象的共同接口
- 代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
- 真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。
应用场景:
构建一个对象很耗费时间和计算机资源,代理模式(Proxy)允许我们控制这种情况,直到我们需要使用实际的对象。(如:比如一幅很大的图像,需要载入的时间很长)
动态代理在spring的AOP中应用很多:spring动态代理主要有2种:JDK反射机制();cglib
缺点:
由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
Spring AOP的2种动态代理方式
1. JDK反射机制
http://blog.csdn.net/intlgj/article/details/5671927
实现Java.lang.reflect.InvocationHandler接口,复写其中的invoke方法。
涉及1个接口和1个类:
- 接口: InvocationHandler。唯一方法:public object invoke(Object obj,Method method, Object[] args):第一个参数obj一般是指代理类,method是被代理的方法,如上例中的request(),args为该方法的参数数组。
- 类:Proxy。动态代理类,运行时生成的class,在生成它时你必须提供一组interface给它,然后该class就宣称它实现了这些 interface。不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。
2. cglib
http://blog.csdn.net/wsh622827/article/details/4708329
cglib(Code Generation Library)是一个强大的,高性能,高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口。cglib封装了asm,可以在运行期动态生成新的class。asm 是一个强大的 Java 字节码生成框架,和 BCEL 或者 SERP 很类似,但是小很多,可以动态修改 java 字节码。
cgLib 可以不用接口,它底层调用asm 动态生成一个代理类去覆盖父类中非 final 的方法,然后实现 MethodInterceptor 接口的 intercept 方法,这样以后直接调用重写的方法,比 JDK 要快。但是加载 cglib 消耗时间比直接 JDK 反射时间长,开发的过程中,如果是反复动态生成新的代理类推荐用 JDK 自身的反射,反之用 cglib。