一、代理模式的概念
代理(Proxy)模式:为其他对象提供一个代理以控制对某个对象的访问,即通过代理对象访问目标对象
二、代理模式的实现
1、静态代理
在程序运行前就已经存在代理类的字节码文件
代理类和委托类的关系在运行前确定
//统一接口
public interface Subject{
public void doAction();
}
//委托类
public class RealSubject implements Subject{
public void doAction(){
//TODO
}
}
//代理类
public class MyProxy implements Subject{
//目标对象
private Subject realSubject;
public MyProxy(Subject realSubject){
this.realSubject = realSubject;
}
public void doAction(){
//before TODO
realSubject.doAction();
//after TODO
}
}
pros and cons :
在目标方法调用前后增加处理过程(日志、权限等)
代理类和委托类实现了相同的接口,出现了大量重复代码(如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法)
每个代理对象只服务于一种类型的对象(代理对象需要实现与委托对象相同的接口)
2、动态代理
在程序运行期间由JVM根据反射等机制动态生成代理类的源码
代理类和委托类的关系是在运行时确定
2.1 JDK动态代理
java.lang.reflect包提供Proxy类和InvocationHandler接口
//接口
public interface Subject{
public void doAction();
}
//委托类
public class RealSubject implements Subject{
public void doAction(){
//TODO
}
}
//调用处理器
public class Handler implements InvocationHandler {
//目标对象
private Subject realSubject;
public Handler(Subject realSubject){
this.realSubject = realSubject;
}
/**
* proxy——代理对象
* method——目标方法
* args——目标方法实参
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//before TODO
Object object = method.invoke(realSubject, args);
//after TODO
return object;
}
}
public class Test {
public static void main(String[] args) {
//委托对象
Subject realSubject = new RealSubject();
//调用处理器(与委托对象关联)
InvocationHandler handler = new Handler(realSubject);
//代理对象(代理对象方法的调用触发Handler中invoke方法的执行)
Subject subjectProxy = (Subject)Proxy.newProxyInstance(
Subject.class.getClassLoader(),new Class<?>[]{Subject.class}, handler);
subjectProxy.doAction();
}
}
深入剖析 \ ( > < ) /……
pros and cons :
对代理类的函数进行统一的处理,不用修改每个代理类中的方法(所有被代理执行的方法通过InvocationHandler中的invoke方法调用的,只要在invoke方法中统一处理,就可以对所有被代理的方法进行相同的操作)
只能对接口实现代理(动态生成的代理对象实际继承【extends】Proxy类实现【implements】目标接口)
2.2 CGLIB动态代理
cglib是针对类(接口也行)来实现代理,对指定的类生成一个子类,并覆盖其中方法实现代理
因为采用的是继承,所以不能对final修饰的类进行代理
//接口
public interface Subject{
public void doAction();
}
public class Interceptor implements MethodInterceptor {
//实现回调方法
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)
throws Throwable {
//before TODO
//调用业务类(父类中)的方法
proxy.invokeSuper(obj, args);
//after TODO
return null;
}
public class Test{
Subject realSubject = new RealSubject();
//拦截器
MethodInterceptor intercepter = new Intercepter();
//增强器
Enhancer enhancer = new Enhancer();
//给代理类指定父类
enhancer.setSuperClass(realSubject.getClass());
//设置回调(代理类上所有方法的调用都会调用Callback,Callback需要实现intercept()方法进行拦截)
enhancer.setCallback(intercepter);
//创建代理对象
Subject subjectProxy = (Subject)enhancer.create();
subjectProxy.doAction();
}
深入剖析 \ ( > < ) /……
三、代理模式的应用
Spring AOP 的实现
可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能
不要随意去修改别人写好的代码或者方法,需要时可以通过代理的方式来扩展
四、代理模式の其他问题
静态代理是在代码中显式定义一个代理类,通过代理类同名的方法调用被包装过的业务方法
JDK动态代理是通过接口中的方法名,在动态生成的代理类中调用业务实现类的同名方法
CGLIB动态代理是通过继承业务类,生成的动态代理类是业务类的子类,通过重写业务方法进行代理
五、Reference
六、Resource