【动态代理】invoke 方法详解、动态代理流程梳理

【动态代理】invoke 方法详解、动态代理流程梳理

这下面的注释是我模拟mybatis 底层的时候写的,作为对【动态代理】的复习。

/**
 * 再次复习这个invoke 方法!
 * 口述动态代理设计到的一些关键的类或接口说明:
 *  1.生成动态代理对象$Proxy0 靠的是 Proxy.newProxyInstance(ClassLoader,interfaces,invocationHandler的实现类)
 *  2. 这里的重点是第三个参数 invocationHandler的实现类
 *  3. InvocationHandler 是一个接口,故可以用 匿名内部类 或 implement 的方式得到该接口的实现类
 *      这里采用implement 的方式
 *  4. InvocationHandler 接口中有一个 public Object invoke(Object proxy, Method method, Object[] args) 方法
 *  5. 第一个参数: Object proxy:传参时传入的是代理对象 $Proxy0
 *      5.1 $Proxy0 是一个JDK 底层生成的类,该类继承了Proxy 类,实现了 对应的接口
 *  6. 第二个参数: Method method :是目标对象的方法对象,用于反射调用目标方法
 *  7. 第三个参数:可变参数类型,表示调用方法时传入的参数
 *  8.invoke() 方法的返回值是目标方法执行完返回的结果
 *
 *  动态代理执行流程:
 *      1.通过Proxy.newProxyInstance() 方法得到代理对象$Proxy0  ,习惯上,我们用目标接口来接收。如果要看其运行类型,要用getClass()方法来看
 *      2.代理对象$Proxy0 调用目标方法 ==》 getSub() 方法
 *      3.精彩部分来了!
 *          3.1  根据动态绑定机制,代理对象调用getSub() 方法,会调用$Proxy0 自己写的 getSub()方法,文末
 *          3.2  $Proxy0 getSub() 方法其实调用的是invocationHandler实现类的invoke() 方法 ==》return (Double)super.h.invoke(this,
 *          m3, new Object[]{var1, var3})
 *          3.3  super表示Proxy对象,因为$Proxy0 实现了Proxy类嘛
 *          3.4  h 表示invocationHandler实现类
 *          3.5  invoke 表示invocationHandler实现类 的invoke() 方法,也就是我们重写的invoke()方法
 *          3.6  invoke(this, m3, new Object[]{var1, var3})
 *               ==> this表示$Proxy0 对象本身
 *               ==> m3 表示目标方法对象
 *               ==> new Object[]{var1, var3} 表示传入的参数数组
 *       4. invoke() 方法中,会调用目标对象原本的方法,再执行一些我们增强的内容
 *
 *  总之一句话:代理对象通过动态代理,最终会绑定到我们重写的invoke() 方法!!!
 *
 *
 *  通过反编译,得到$Proxy0 的class 文件,摘取部分关键代码
 *          public final class $Proxy0 extends Proxy implements SmartAnimal
 *
 *            m3 = Class.forName("org.pig.spring.aop.advancedproxy.mine.proxyversion.SmartAnimal").getMethod
 *            ("getSub", Double.TYPE, Double.TYPE);
 *
 *      public final double getSub(double var1, double var3) throws  {
 *         try {
 *             return (Double)super.h.invoke(this, m3, new Object[]{var1, var3});
 *         } catch (RuntimeException | Error var6) {
 *             throw var6;
 *         } catch (Throwable var7) {
 *             throw new UndeclaredThrowableException(var7);
 *         }
 *      }

代理对象$Proxy0 的class 文件如下

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.sun.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import org.pig.spring.aop.advancedproxy.mine.proxyversion.
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值