文章目录
推荐大家去看动力节点的视频,更有助于理解
代理模式
一、如何理解代理模式
通过老杜的方法(类比现实场景)来理解代理模式,如下:
1、代理模式的三大角色:目标对象、代理对象、公共接口
拍电影 | 代理模式 | |
---|---|---|
第一个角色 | 演员 | 目标对象 |
第二个角色 | 替身演员 | 代理对象 |
第三个角色 | 演员和替身演员具有相同的动作行为 | 目标对象和代理对象的公共接口 |
下面有代码去展示:
三者的关系图如下:
- 三个之间的关系就是,目标对象和代理对象都实现了同一个公共接口
2、代理模式的三个作用
1)保护自己
- 在程序中,当一个对象需要受到保护的时候,可以考虑使用代理对象去完成某个行为。
- 现实场景中, 演员害怕手上让替身演员(代理解析)演出,实现保护自己的作用
2)增强功能
- 在程序中,需要给某个对象的功能进行功能增强的时候,可以考虑找一个代理进行增强。
- 现实场景中,比如我们要租房子,可以自己租(目标对象),也可以找中介组(代理对象),实现了增强功能
3)代理交互
- 在程序中,A对象无法和B对象直接交互时,也可以使用代理模式来解决。
- 现实场景中,相亲前双方男女没见面,媒婆通过联系双方的父母(代理对象),实现了不同对象的沟通。
3、代理模式的实现方式
分为静态代理和动态代理
接下来会详细阐述
二、静态代理
1、深入浅出,从一个现实业务中常见的场景出发
引入老杜的例子:
某个项目的某个业务模块已经正常运行多年,项目经理要求对这些模块进行优化。首先提出的第一步简单的需求:要求显示每个模块(方法)执行的时间。比如我现在拿到这么一个需求,应该如何实现呢?
1)方法一,硬编码,直接修改原业务代码,在其基础上新增一个计时的业务代码。
分析其优缺点
- 优点:简单易懂,硬编码十分粗暴
- 缺点:违反了OCP开闭原则,并且代码冗余
插一个知识点,什么是OCP开闭原则?
开闭原则 (The Open/Closed Principle, OCP) 规定“软件中的对象(类,模块,函数等等)应该对于扩展是开放的,但是对于修改是封闭的” 。其含义是说一个软件实体应该通过扩展来实现变化,而不是通过修改已有的代码来实现变化的。
该特性在产品化的环境中是特别有价值的,在这种环境中,改变源代码需要 代码审查 , 单元测试 以及诸如此类的用以确保产品使用品質的过程。
2)方法二:新建类继承原业务,在子类中重写父类的方法,实现业务需求
分析优缺点
- 优点:遵守了OCP开闭原则
- 缺点:代码一样冗余,而且增加了耦合度(因为采用了继承关系)
3)引入代理模式,即使用代理对象,实现功能增强的作用
刚才提到,代理模式所需要的三大角色:目标对象,代理对象,公共接口,正常的业务中已经实现了【目标对象+公告接口】,还缺的就是一个代理对象。
那么代理对象在编码层就很简单,创建一个对象并实现公告的接口,同时,要求客户端在使用代理对象时,就行在使用目标对象一样!
那么,静态代理在代码中如何实现呢?
- 首先创建一个代理对象并实现同一个公共接口
- 正常重写父类方法,并写好增强功能所需的业务逻辑
- 引用 目标对象(如何引用?
- 在代理对象内,调用目标对象的所对应的方法、
如何引用目标对象?看代码
插入知识点:类与类之间的关系之二的【泛化关系和关联关系】
- 泛化关系,就是继承,是一种
is a
的关系
- 比如说,苹果是水果,猫是动物,这是泛化关系
- 关联关系,即引用,是一种
has a
的关系
- 比如,人拥有苹果,人拥有猫,这是关联关系
2、静态代理模式有什么有优缺点
优点:
- 解决了OCP问题
- 使用了关联关系,引入了has a的关系,降低了耦合
缺点
-
代码依然冗余,假设系统中接口过多,每个接口都有一个代理对象,会出现【类爆炸】的情况
-
不好维护(类过多,不利于后期再修改业务
为了克服静态代理模式的缺点,引入了动态代理
在内存中动态生成字节码代理类的技术,叫做,动态代理
动态代理还是代理模式,只不过添加了字节码生成技术,可以在内存中为我们动态的生成一个cLass 字节码,这个字节码就是代理类。
三、动态代理
1、什么是动态代理?
前面已经提到了,动态代理就是【在内存】中动态生成【字节码代理类】的技术。(虽然不需要开发者书写,但是在内存层面依然存在该代理对象】
优点:
- 减少了代理类的数量
- 并且解决了代码复用的问题。
动态代理常见的实现技术包括以下三种
- JDK内置的动态代理技术 :只能代理接口
- 位置:java.lang.reflect.Porxy ,是一个注解
- CGLIB(Code Generation Library)动态代理技术,一个开源项目,生成类库,可以适用于接口和类
- 但是CGLIB的低层是通过【继承】实现的(虽然是继承,但是由于是在内存动态生成字节码类,所以并不会增加耦合度),所以性能比JDK动态代理好
- CGLIB的低层还有一个字节码处理框架 【ASM】(可能阅读源码时会遇到)
- Javassist动态代理技术:东京大学的千叶滋教授所创建的开源项目。为JBOOS实现“aop”框架
- mybatis框架底层就是用的javassist创建接口的字节码对象
Spring的低层主要是靠JDK内置的动态代理和CGLIB实现