代理模式
概念:为其他对象提供一种代理一控制对这个对象的访问。
Provide a surrogate or placeholder for another object to control access to it.
适用场景:远程调用的网络代理、考虑安全因素的安全代理、提升系统性能的初始化代理等。
代理模式类图
涉及三个角色:
- Subject抽象主题
可以是抽象类也可以是接口,普通业务类型定义 - RealSubject具体主题
被委托角色,业务逻辑具体执行者 - Proxy代理主题
代理类 (委托类),抽象主题定义的方法限制委托给RealSubject实现,并在其前后做预处理和后处理工作。
基本代码:
public interface Subject {
//定义一个方法
public void request();
}
public class RealSubject implements Subject {
//实现方法
@Override
public void request(){
}
}
public class Proxy implements Subject {
//要代理的实现类
private Subject subject = null;
public Proxy(){
this.subject = new Proxy();
}
public Proxy(Object ... objects){
}
//实现接口中定义的方法
@Override
public void request(){
this.before();
this.subject.request();
this.after();
}
//预处理
private void before(){
//do something
}
//后处理
private void after(){
//do something
}
}
动态代理
概念:在运行阶段才确定代理哪一个对象,实现阶段不必关心。代理类的字节码将在运行时生成并载入当前的ClassLoader。
Java 1.3以后,java提供了动态代理技术,允许开发者在运行期间创建接口的代理实例。
实现上主要涉及java.lang.reflect
包中的Proxy
和 InvocationHandler
JDK创建代理只能为接口创建代理实例,cglib采用底层的字节码技术,可以为一个类创建子类,在子类中采用方法拦截的技术拦截父类方法的调用并顺势织入横切逻辑。由于cglib采用动态创建子类的方式生成代理对象,所以不能对目标类中的final或private方法进行代理。
Spring AOP的底层就是通过JDK或cglib动态代理技术为目标Bean织入横切逻辑,其中cglib创建的动态代理对象性能高,但是创建代理对象所花费的时间比JDK动态代理长,因此对于singleton的代理对象或者具有实例池的代理,因为无需频繁创建代理对象,适合采用cglib方式,反之则适合采用jdk动态代理技术。