代理模式
静态代理
由程序员或者自动生成工具生成代理类,然后进行代理类的编译和运行。在代理类、委托类运行之前,代理类已经以.class的格式存在。
介绍
意图: 给实体类添加功能
注意事项:
- 装饰器的阉割版,只有一个代理类实现时可以使用
- 可以用继承实体类替代
JDK动态代理
在程序运行时,由反射机制动态创建而成。
介绍
意图: 动态为实体类添加功能
优点:
- 代理工厂类与实际调用类完全解耦
缺点:
- 返回的代理类需要强制转换为实体类类型
注意事项:
有时为了隐藏实体类转换过程,将proxyFactory继承Subject,重写所有方法的的实现。参考:mybatis中对SqlSessionFactory的处理[^org.apache.ibatis.session.SqlSessionManager]
CGLIB动态代理
基于子类的动态代理类创建,与JDK动态代理区别:无需接口类
此处省略类图,自己脑补。把JDK动态代理类图中,接口类Subject去掉即可。
介绍
主要用途
- 远程代理(remote proxy),为远程对象提供一个本地的代理对象。例:RMI,EJB,local bean
- 虚拟代理(virtual proxy),对象在第一次被使用时才会创建,用代理对象替代真实对象初始化。
- 写入是复制代理(copy-on-write proxy),控制对象的复制,在第一次对复制后对象执行写操作时,才会真的去复制。是虚拟代理的一个变体。
- 保护代理(protection (access)proxy),为不同客户提供不同级别的目标对象访问权限。
- 缓存代理(cache proxy),为开销大的运算结果提供缓存,允许不同客户共享。降低访问延迟
- 防火墙代理(firewall proxy),控制网络资源的访问,保护主题免受恶意客户的伤害。
- 同步代理(synchronization proxy),在多线程情况下,为主题提供安全的访问。
- 智能引用代理(smart reference proxy),当一个对象被引用时,提供一些额外功能。例如:记录调用次数等。
- 复杂隐藏代理(complexity hiding proxy),为了隐藏一个类的复杂度,并进行访问控制,有时也称为外观代理(facade proxy)。效果与外观模式类似,只是采用代理控制访问。
[^org.apache.ibatis.session.SqlSessionManager]: https://github.com/mybatis/mybatis-3/blob/master/src/main/java/org/apache/ibatis/session/SqlSessionManager.java 源码地址