代理模式的简单介绍
代理模式是给对象创建一个代理对象,这个代理对象就像是我们生活中的中介一样,我们将买房这件事情委托给中介,中介能够帮我们把买房这件事实现,并且他们会在买房这个过程中完成找客户,收中介费等操作。
代理模式的类图
代理模式又细分为两种:
- 静态代理
构建一个代理对象,代理对象可以通过真实对象调用对应的方法,并且在实现真实对象方法之外做一些其他事情。
动态代理
动态代理的特点就是,代理对象不需要我们手动创建,而是动态根据真实对象创建出来的。
Java的动态代理主要有两种形式
- jdk动态代理
- Cglib动态代理
代理模式的具体实现思路
静态代理
- 创建抽象对象
- 创建真实对象
- 创建代理对象
动态代理
- 创建接口(可以不创建)
- 创建目标对象
- 创建接口的通过JDK实现动态代理,未创建的通过Cglib实现动态代理
代理模式的具体实现方案
静态代理
// 抽象对象 public interface AbstractSubject { void request(); } // 真实对象 public class RealSubject implements AbstractSubject { public void request(){ } } // 代理对象 public class ProxySubject implements AbstractSubject { private RealSubject realSubject; public ProxySubject(RealSubject realSubject){ this.realSubject = realSubject; } public void request(){ // 其它操作 realSubject.request(); // 其它操作 } }
动态代理
JDK动态代理
JDK实现代理只需要使用java.lang.reflect.Proxy的newProxyInstance方法
// JDK动态代理 public class ProxyFactory{ // 需要被代理目标对象 private Object target; public ProxyFactory(Object target){ this.target=target; } // 通过动态代理为目标对象生成代理对象 public Object getProxyInstance(){ return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 其它操作 // 执行目标对象的方法 Object returnValue = method.invoke(target, args); // 其它操作 return returnValue; } } ); } }
Cglib动态代理 通过创建子类实现代理
public class ProxyFactory implements MethodInterceptor{ // 需要被代理目标对象 private Object target; public ProxyFactory(Object target) { this.target = target; } // 通过动态代理为目标对象生成代理对象 public Object getProxyInstance(){ // 1.工具 Enhancer en = new Enhancer(); // 2.设置父类 en.setSuperclass(target.getClass()); // 3.设置回调函数 en.setCallback(this); // 4.创建子类(代理对象) return en.create(); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { // 其它操作 // 执行目标对象的方法 Object returnValue = method.invoke(target, args); // 其它操作 return returnValue; } }
代理模式的优缺点
优点
- 保护目标对象。
- 通过代理对象,增强目标对象,我们只需要修改代理类而不需要再修改委托类,符合代码设计的开闭原则。
缺点
- 调用复杂度升高,可能会影响执行效率
- 问题可能会出在代理对象上,不利于排查问题
代理模式的适用场景
- 在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。
- 代理类可以为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后对返回结果的处理等。
- 代理类本身并不真正实现服务,而是同过调用委托类的相关方法,来提供特定的服务。真正的业务功能还是由委托类来实现,但是可以在业务功能执行的前后加入一些公共的服务。
例如:给项目加入缓存、日志这些功能,我们就可以通过代理类来完成,而没必要修改已经封装好的委托类。
Spring 的AOP就是对动态代理的一种封装,我们利用AOP去实现的一些功能,其实就是在使用代理模式进行开发。
代理模式总结
代理模式可以说是最实用的一种设计模式,尤其是在解决一些通用问题时,效果极佳,比如日志,我们需要记录入参和出参,还有访问的是哪个方法,使用动态代理的话,能够极大的减少我们的代码量,本来需要每个方法写一遍,有了动态代理,我们只需要将这些重复代码写在代理类中,这样我们就可以实现面向切面开发。