本文主要是介绍Java基础回顾:代理,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
1)静态代理
代理模式为其他对象提供一种代理以控制对这个对象的访问
通过静态代理,我们达到了功能增强的目的,而且没有侵入原代码,这是静态代理的一个优点。
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在系统中的冗杂问题了。
JDK动态代理步骤:
- 获取RealSubject上所有的接口列表;
- 确定要生成的代理类的类名,默认为:com.sun.proxy.$ProxyXXXX;
- 根据需要实现的接口信息,在代码中动态创建该Proxy类的字节码;
- 将对应的字节码转换为对应的class对象;
- 创建 InvocationHandler 实例 handler,用来处理Proxy所有方法调用;
- Proxy的class对象以创建的handler为参数,实例化一个proxy对象。
代码实例:
第一步:新建一个UserService接口,以及定义一些方法
第二步:新建一个接口实现类UserServiceImpl,实现接口方法
第三步:新建一个UserHandler类实现InvocationHandler接口
第四步:使用Proxy.newProxyInstance生成代理类 测试
3)动态代理 - CGLib(通过继承类的方式)
CGLIB创建动态代理类的模式是:
- 查找目标类上所有的非final的public类型的方法定义;
- 将这些方法定义转成字节码;
- 将组成的字节码转换成相应的代理的class对象;
- 实现MethodInterceptor接口,用来处理代理类上的所有方法请求
第一步:新建一个类,并定义实现方法
第二步:定义一个类LogInterceptor实现net.sf.cglib.proxy.MethodInterceptor
第三步:定义net.sf.cglib.proxy.Enhancer
结果:
如果要对一个类中不同方法实现不同的拦截策略,实现下面例子:
第四步:再定义一个拦截类
第五步:新增一个类继承CallbackFilter定义过滤规则(如下,select方法使用第0个拦截,其他方法使用第1个拦截)
第六步:修改Enhancer
结果:
4)JDK和CGLib动态代理对比
JDK动态代理:基于Java反射机制实现,必须要实现了接口的业务类才能使用这种办法生成代理对象;
CGLib动态代理:基于ASM机制(Java 字节码操控框架,能够以二进制形式修改已有类或者动态生成类)实现,通过生成业务类的子类作为代理类
JDK Proxy优势:
- 最小化依赖关系,减少依赖意味着简化开发和维护,JDK本身支持,可能更可靠;
- 平滑进行JDK版本升级
- 代码实现简单
CGLib动态代理优势:
- 无需实现接口,达到代理类无侵入
- 只操作我们关心的类
- 高性能
参考:
https://juejin.cn/post/6844903807755747342
https://juejin.cn/post/6844903744954433544
https://www.cnblogs.com/xrq730/p/6661692.html
这篇关于Java基础回顾:代理的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!