为啥要学习代理模式?
因为代理模式是AOP的底层,我们要学习AOP就必须学会代理模式
代理模式的分类:
- 静态代理
- 动态代理
静态代理:
- 角色分析:
- 抽象角色:一般会使用接口或者抽象类来解决
- 真实角色:被代理的角色
- 代理角色:代理真实角色,代理真实角色后,我们一般会做一些附属操作
- 客户:访问代理对象的人!
我们先看下之前没有代理模式的时候,我们的业务是怎么设计的:
代码体现:
1.写个接口:确定这个业务是做什么的,即我们所谓的抽象角色
2. 写一个实现类,去实现这个业务接口,即我们所谓的真实角色
3.再写一个实体类:调用我们的实现类去实现这个业务,即我们所谓的客户
上述就是我们基本的业务实现过程,但是这里如果出现一种情况,就是上述如果我这个客户,去找房东,也就是上述的那个实体类,发现找不到房子了,只能去中介找房子,那么我们这个代理的概念就出来了:
我们写一个代理类,来去代理我们的实现类:
注意:既然这里我们要帮实现类去实现业务,那么肯定要去实现业务接口的
那我们再用这个实体类利用代理类去实现业务:
分析一下:这里是不是和我们之前讲的IOC原理有些相似,唯一区别就是IOC是提供set外部接口实现了控制反转,而代理模式这边是通过有参构造器实现的控制反转,其实这不是重要的,因为这里只是演示,一般还是利用set方式实现控制反转!重要的是我们利用了IOC理念实现了代理模式,通过访问代理类来实现原有的业务逻辑,其次就是代理类还可以有自己额外的附属操作,这是原有的真实角色达不到的动作!
对于附属操作,我们可以这样演示:
比如说一些动作,真实角色不能做,而代理角色可以做,
代理模式的好处:
- 可以使真实角色的操作更加纯粹!不用去关注一些公共的业务
- 公共业务逻辑也就交给代理角色去实现了【不改变真实角色代码逻辑,在代理角色中实现,或者进行业务扩充】
- 公共业务逻辑发生扩展的时候,方便集中管理!
代理模式的缺点:
- 一个真实角色会产生一个代理角色,那你一个项目里有几十个真实角色,那么你的代理类是不是就有几十个啊,那么代码量就会翻倍,开发效率会变低
动态代理:
-
动态代理和静态代理的角色一样
-
动态代理的代理类是动态生成的,不是我们直接写好的
-
动态代理分为两大类:1.基于接口的动态代理 :JDK动态代理 2.基于类的动态代理:cglib
需要了解两个类:proxy【类】:代理 invocationHandler【接口】:调用处理程序
上述两个类都是反射包下的,对于invocationHandler来说,它就是每个代理类都会关联一个调用处理程序,用调用处理程序invocationHandler来处理代理类
代码实现一下:
1. 抽象角色还是之前的,就是我们实现业务逻辑的接口
2.真实角色还是之前的实现了抽象角色接口的实现类:
3.创建一个处理类,就用这个类来自动生成我们的代理类
前面我们说了 ,invocationHandler【接口】:调用处理程序,就是用调用处理程序invocationHandler来处理代理类,所以我们创建的这个类是不是要实现invocationHandler接口才行啊,实现了接口,我们重写接口的invoke方法,这个方法是用来处理代理类的,并返回一个结果,我们创建的这个类中还需要上述说的proxy【类】,它调用静态方法是用来生成代理类的,而这个静态方法里需要的参数有本类的类加载器,以及代理接口,这个代理的接口其实就是抽象角色的接口,即我们实现业务逻辑的接口,最后还需要一个实现了invocationHandler接口的实体类 ,那么我们当前创建的这个类不就是嘛,所以写this就可以了
4.创建客户类,访问代理对象:
首先我们通过new这个处理类,然后通过set外部接口将我们的真实角色进行注入,这样我们这个类再调用获取代理类的方法就可以获取到代理类了,那么我们处理中的重写了invoke方法用在哪了呢?还记得我们获取代理类中的第三个参数吗?就是invocationHandler【接口】:调用处理程序,这个获取代理类的方法中就是利用了这个实现了invocationHandler【接口】的处理类在底层去执行调用处理程序invoke方法,利用反射机制实现了真实角色中业务逻辑的执行
5.动态代理实现代理类的附属操作:
只需将我们的附属操作,放入我们invocationHandler【接口】处理类:调用处理程序的invoke方法里就可以了
动态代理的好处:
- 可以使真实角色的操作更加纯粹!不用去关注一些公共的业务
- 公共业务逻辑也就交给代理角色去实现了【不改变真实角色代码逻辑,在代理角色中实现,或者进行业务扩充】
- 公共业务逻辑发生扩展的时候,方便集中管理!
动态代理封装成工具类的演示:
静态代理和动态代理的区别:
对于静态代理来说,上述讲过,一个真实的类就需要产生一个代理类的说法其实是不准确的,因为我们的静态代理类其实也可以做到封装成一个工具类来使用,与动态代理无异,那么动态代理和静态代理的区别到底在哪里?
区别:
实际上是在真实角色所负责的业务逻辑上,我们的静态代理可以抽取成工具类,并且可以进行多实现,达到最大程度上的代理,可以代理多个真实角色,但是缺点也特别明显,就是你这个静态代理工具类要重写的真实角色业务逻辑方法是不是一样就变多了,你想想,那得重写多少方法啊,代码量是不是特别大,那么对于动态代理来说,它是利用了反射的机制来实现代理的,它是对接口的代理,所以完全不需要我们重写真实角色的业务逻辑方法,这其实就是动态代理相较于静态代理最大的优点