【动态代理】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.