代理模式
在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。
在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。
意图:
为其他对象提供一种代理以控制对这个对象的访问。何时使用:
想在访问一个类时做一些控制。
几种实现代理的实现:
- 静态代理,如通过继承或聚合实现
- 动态代理,如jdk动态代理或cglib动态代理
术语:
- 代理对象:增加控制逻辑后的对象(增强后的对象)
- 目标对象:要增加控制逻辑的对象(要增强的对象)
静态代理
继承代理
代理对象继承目标对象,重写需要增强的方法
缺点:当有多个代理业务时,代理类数量随之增多,如果要组成代理链路则类会更多且复杂
聚合代理
目标对象和代理对象实现同一个接口,代理对象当中要包含目标对象。
缺点:代理类也会随业务增多,但相比继承代理,组成代理链路时不需要创建新的继承链路类
动态代理
jdk动态代理
JDK的动态代理只允许动态代理接口,因为动态生成的代理类继承了Proxy
类,基于java单继承的原则所以只可代理接口
只能动态代理接口是设计猜测,因为动态代理一个类存在一些问题。在代理模式中代理类只做一些额外的拦截处理,实际处理是转发到原始类做的。。如果允许动态代理一个类,则代理类需要继承目标类,那么代理对象也会继承目标类的所有字段,而这些字段是实际上是没有使用的,对内存空间是一个浪费。因为一般业务代理对象只做方法的拦截转发处理,对象的字段存取都是在原始对象上处理。更为致命的是如果代理的类中有final的方法,动态生成的类是没法覆盖这个方法的,没法代理,而且存取的字段是代理对象上的字段,这显然不是我们希望的结果。spring aop框架就是这种模式
仿动态代理
jdk只能代理接口而不能代理类是因为动态生成的代理类继承了Proxy
类,如果改为继承代理目标类
则可实现类的代理
动态代理的实现步骤:
- 生成java源码文件
- 将java文件动态编译为class字节码文件
- 通过类加载器将class字节码文件加载到jvm当中,获取Class对象
以下示例,为了可读性,生成代理类java源文件未判断方法只否可重写、及代码的优化
使用示例: