定义:是为某个对象提供一个代理对象,由代理对象控制对目标对象的访问。
结构型
优点:
1、职责清晰,将代理对象与真实的被调用的目标对象分离,代理类和委托类实现相同的接口。
2、高扩展性,可以通过给代理类增加额外的功能来扩展委托类的功能,降低了系统的耦合性,符合开闭原则。。
3、智能化,保护目标对象,增强目标对象。
缺点:
1、由于在客户端和目标对象之间增加了代理对象,可能会造成请求的处理速度变慢。
2、实现代理模式需要额外的工作,增加系统的复杂度。
使用场景:
按职责来划分,通常有以下使用场景:
1、远程代理。
2、虚拟代理。
3、Copy-on-Write 代理。
4、保护(Protect or Access)代理。
5、Cache代理。
6、防火墙(Firewall)代理。
7、同步化(Synchronization)代理。
8、智能引用(Smart Reference)代理。
代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后对返回结果的处理等。
代理类本身并不真正实现服务,而是通过调用委托类的相关方法,来提供特定的服务。
1静态代理:
由程序员创建或特定工具自动生成源代码,再对其进行编译。在程序运行之前,代理类.class文件就已经被创建,代理类和委托类的关系在运行前就确定。每个代理类只能为一个接口服务,在编译器就已经确定被代理的对象
2JDK动态代理:
动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以不存在代理类的字节码文件。
动态代理是在程序运行时确定代理类和委托类的关系,通过反射机制实现动态代理,并且能够代理各种类型的对象。
动态代理类只能代理接口(不支持抽象类),代理类都需要实现InvocationHandler
类,实现invoke
方法。 java.lang.reflect.InvocationHandler;
invoke方法就是调用被代理接口的所有方法时需要调用的,返回的值是被代理接口的一个实现类。
使用场景:日志系统、事务、拦截器、权限控制
CGLIB:
CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。
采用的是继承代理目标类,不能对final修饰的类进行代理。
JDK和CGLIB:
CGLIB创建的动态代理对象比JDK创建的动态代理对象的性能更高,但是CGLIB创建代理对象时所花费的时间却比JDK多。
无需频繁创建对象,用CGLIB合适,反之使用JDK方式要更为合适一些。
注:执行效率:万次执行时,JDK7、8的效率比CGLIB 快20%左右
Spring代理选择:
当bean实现了接口,,默认使用JDK代理;
当bean没有实现接口,默认使用CGLIB代理;
也可强制使用CGLIB代理;aop配置属性:proxy-target-class="true"
注意事项:
1、和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。
2、和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了控制对目标对象的访问。
参考链接:
https://www.jianshu.com/p/9cdcf4e5c27d
https://www.runoob.com/design-pattern/proxy-pattern.html