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://www.cnblogs.com/xrq730/p/6661692.html

posted @ 2021-10-17 18:52  fanghuiX  阅读(37)  评论(0编辑  收藏  举报