Java基础回顾:代理
1)静态代理
代理模式为其他对象提供一种代理以控制对这个对象的访问
通过静态代理,我们达到了功能增强的目的,而且没有侵入原代码,这是静态代理的一个优点。
![](https://img2020.cnblogs.com/blog/1461236/202110/1461236-20211017184535186-543842434.png)
class Proxy extends Subject {
private RealSubject real;
@Override
public void Request() {
if (null == real) {
real = new RealSubject();
}
real.Request();
}
}
优点:访问无法访问的资源,增强现有的接口业务功能
缺点:大量使用这种静态代理,会使我们系统内的类的规模增大,并且不易维护,这种代理在系统中存在,导致系统结构比较臃肿和松散。
2)动态代理 - JDK(通过实现接口的方式)
*** JDK代理是基于实现接口的方式
主要涉及类和接口:
- java.lang.reflect.Proxy
- java.lang.reflect.InvovationHandler
动态代理,是需要代理的地方,根据Subject和RealSubject,动态的创建一个Proxy,用完之后,就会销毁,这样就可以避免Proxy角色的class在系统中的冗杂问题了。
![](https://img2020.cnblogs.com/blog/1461236/202110/1461236-20211017184559159-1939799176.png)
JDK动态代理步骤:
- 获取RealSubject上所有的接口列表;
- 确定要生成的代理类的类名,默认为:com.sun.proxy.$ProxyXXXX;
- 根据需要实现的接口信息,在代码中动态创建该Proxy类的字节码;
- 将对应的字节码转换为对应的class对象;
- 创建 InvocationHandler 实例 handler,用来处理Proxy所有方法调用;
- Proxy的class对象以创建的handler为参数,实例化一个proxy对象。
代码实例:
第一步:新建一个UserService接口,以及定义一些方法
![](https://img2020.cnblogs.com/blog/1461236/202110/1461236-20211017184612606-682403272.png)
第二步:新建一个接口实现类UserServiceImpl,实现接口方法
![](https://img2020.cnblogs.com/blog/1461236/202110/1461236-20211017184619957-1700964628.png)
第三步:新建一个UserHandler类实现InvocationHandler接口
![](https://img2020.cnblogs.com/blog/1461236/202110/1461236-20211017184629441-1662962809.png)
第四步:使用Proxy.newProxyInstance生成代理类 测试
![](https://img2020.cnblogs.com/blog/1461236/202110/1461236-20211017184637564-689127698.png)
3)动态代理 - CGLib(通过继承类的方式)
![](https://img2020.cnblogs.com/blog/1461236/202110/1461236-20211017184646571-36564725.png)
CGLIB创建动态代理类的模式是:
- 查找目标类上所有的非final的public类型的方法定义;
- 将这些方法定义转成字节码;
- 将组成的字节码转换成相应的代理的class对象;
- 实现MethodInterceptor接口,用来处理代理类上的所有方法请求
第一步:新建一个类,并定义实现方法
![](https://img2020.cnblogs.com/blog/1461236/202110/1461236-20211017184657033-2012514401.png)
第二步:定义一个类LogInterceptor实现net.sf.cglib.proxy.MethodInterceptor
![](https://img2020.cnblogs.com/blog/1461236/202110/1461236-20211017184704969-1569692288.png)
第三步:定义net.sf.cglib.proxy.Enhancer
![](https://img2020.cnblogs.com/blog/1461236/202110/1461236-20211017184714748-259851632.png)
结果:
![](https://img2020.cnblogs.com/blog/1461236/202110/1461236-20211017184725857-1193336205.png)
如果要对一个类中不同方法实现不同的拦截策略,实现下面例子:
第四步:再定义一个拦截类
![](https://img2020.cnblogs.com/blog/1461236/202110/1461236-20211017184736154-990162306.png)
第五步:新增一个类继承CallbackFilter定义过滤规则(如下,select方法使用第0个拦截,其他方法使用第1个拦截)
![](https://img2020.cnblogs.com/blog/1461236/202110/1461236-20211017184746067-1328121724.png)
第六步:修改Enhancer
![](https://img2020.cnblogs.com/blog/1461236/202110/1461236-20211017184813814-650104580.png)
结果:
![](https://img2020.cnblogs.com/blog/1461236/202110/1461236-20211017184822654-622468600.png)
4)JDK和CGLib动态代理对比
JDK动态代理:基于Java反射机制实现,必须要实现了接口的业务类才能使用这种办法生成代理对象;
CGLib动态代理:基于ASM机制(Java 字节码操控框架,能够以二进制形式修改已有类或者动态生成类)实现,通过生成业务类的子类作为代理类
JDK Proxy优势:
- 最小化依赖关系,减少依赖意味着简化开发和维护,JDK本身支持,可能更可靠;
- 平滑进行JDK版本升级
- 代码实现简单
CGLib动态代理优势:
- 无需实现接口,达到代理类无侵入
- 只操作我们关心的类
- 高性能
参考:
https://www.cnblogs.com/xrq730/p/6661692.html
一点浩然气,千里快哉风!