两种动态代理实现方式浅析(jdk与cglib)

 jdk动态代理生成:

  1. /** 
  2.  * jdk 动态代理生成 代码分析 
  3.  * @author quz 
  4.  */  
  5.   
  6. // 需要继承InvocationHandler  
  7. public class Analysis implements InvocationHandler {  
  8.     @Override  
  9.     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
  10.         return null;  
  11.     }  
  12. }  

这里继承的InvocationHandler 里面需要实现一个invoke 方法

Proxy:代理对象

Method:需要实现的方法

Args:传递的参数

  1. // 需要继承InvocationHandler  
  2. public class Analysis implements InvocationHandler {  
  3.       
  4.     // 注入被代理类  
  5.     Object target;  
  6.       
  7.     // 构造器传参  
  8.     public Analysis(Object target) {  
  9.         this.target = target;  
  10.     }  
  11.   
  12.     @Override  
  13.     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
  14.         System.out.println("method pre running....");  
  15.         // 调用目标方法 反射执行  
  16.         Object o = method.invoke(target, args);  
  17.         System.out.println("method after running....");  
  18.         return o;  
  19.     }  
  20.     // 动态生成代理对象  
  21.     public <T> T getProxy() {  
  22.         return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);  
  23.     }  
  24. }  

这里需要传递一个被代理类,使用构造函数进行传递。也就是target需要被构造函数传递,需要让Proxy 去代理生成被代理类,newProxyInstance() 有三个参数

ClassLoader classloader // 获取到类加载器

Class<?> classInfo // 通过反射获取类的信息

this // 当前类,为什么要传递当前类?因为需要在接下来的动态代理生成中,将类的invoke 方法 进行注入. 接下来源码中会有体现.

Proxy 具体如何生成的代理实现?

首先Proxy通过反射获取传递的classInfo,可以拼接成一个类的具体实现,然后在拼接的类实现中注入传递的this,即InvocationHandler 通过传递的InvocationHandler 获取内部的invoke方法,通过classInfo 反射机制 传递method 以及需要被代理的类 注入进去,这样就实现了动态代理

cglib动态代理生成:

  1. public class CglibMethodInterceptor implements MethodInterceptor {  
  2.     /** 
  3.      * cglib 动态代理实现源码分析 
  4.      * @author quz 
  5.      */  
  6.     public Object intercept(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable {  
  7.         System.out.println(">>>cglib动态代理执行开始<<");  
  8.         Object result = proxy.invokeSuper(o, args);  
  9.         System.out.println(">>>cglib动态代理执行结束<<");  
  10.         return result;  
  11.     }  
  12. }  

通过 proxy 生成代理对象 来实现调用方法

通过debug 查看 参数 o 指的是通过字节码生成的代理对象 method 也就是被代理类的方法 args是被代理类方法的参数

  1. public Object invokeSuper(Object obj, Object[] args) throws Throwable {  
  2.     try {  
  3.         this.init();  
  4.         MethodProxy.FastClassInfo fci = this.fastClassInfo;  
  5.         return fci.f2.invoke(fci.i2, obj, args);  
  6.     } catch (InvocationTargetException var4) {  
  7.         throw var4.getTargetException();  
  8.     }  
  9. }  

调用InvokeSuper 方法

This.init 初始化参数

通过init 方法调用后 生成了f1 f2 i1 i2

其中f1 指的是被代理类的对象 f2 指的是代理类对象 i1 指的是被代理类的实现的方法通过索引计算得出的值,i2 指的是代理类实现的方法通过索引计算得出的值。通过传递值的形式,将方法索引传递,得出需要执行的方法是什么,由此不同于jdk动态代理实现,无需反射技术通过索引机制快速调用方法,这也是性能优于jdk动态代理机制的原因。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

quzah

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值