代理模式
代理模式的定义很简单,给某一个对象提供一个代理对象,由代理对象控制原对象的引用。
代理模式需要的几个元素
- 抽象对象角色
- 目标对象角色
- 代理对象角色
具体事例
通过模拟登陆网站来实现代理模式,如网易,像大型网站,采用分布式架构,我们访问的时候通过Nginx,用来做负载均衡。最终访问的路径就是
1 | graph LR |
首先需要一个服务器接口,获取网站的数据。
1 |
|
接着需要实现网易服务器的具体实现,获取网易的标题
1 | public class WYProxy implements Server { |
然而需要通过代理服务器才能访问到该网站,如何访问呢,需要创建一个代理对象。
1 | package com.caoqiwen.learning.design.example5; |
远程IP通过UUID然后对函数取余得到具体ip地址,而实际的网站通过内部server对象获取。
静态代理的缺点
采用静态模式是可以很好的解决代码耦合的问题,但是也存在一些问题。
- 只能服务于Server接口,不能复用,只能新增接口或者新增接口类的实现,会造成类的膨胀。
- Server接口新增一个接口,代理类也需要跟着实现该接口,无法实现类的复用。
JDK中动态代理的实现
1 | public class NginxInvocationHandler implements InvocationHandler{ |
只需要实现InvocationHandler这个接口即可,通过newProxyInstance方法产生实例对象。也是Spring中实现AOP的精华之处。
1 | Server wyServer = new WYServer(); |
动态代理的缺点在于只能产生接口的实例对象,如果需要实例化一个类的动态对象,我们需要用CGLIB来实现。
CGLIB实现动态代理
上面说了对于没有实现接口类如何动态生成对应的对象,我们采用CGLIB就可以实现,在AOP中也用到了CGLIB的动态代理方法。首先来看CGLIB的实现方法。
1 | public class Dao { |
需要定义一个实现类,而不是接口。
1 | public class DaoProxy implements MethodInterceptor { |
通过继承实现MethodInterceptor方法实现,可以在intercept中加入我们需要的业务逻辑。
1 | DaoProxy daoProxy = new DaoProxy(); |
最后一步产生我们需要的类。
需要注意的事项
在maven中需要添加CGLIB的jar文件,还有asm的jar包,否则会提示报错,具体需要添加如下:
1 | <dependency> |