简单介绍一下:
如果不明白动态代理是什么玩意的话,看看其他大佬的博客(他们写的都更详细),我整理的是笔记,一点点自己的理解。
jdk 动态代理,底层实现 就是 java 反射嘛,源码 大体实现逻辑:
- 动态生成代理类 $Proxy0.java , 然后再编译成 $Proxy0.class (0是 动态生成代理类的下标,例如:$Proxy1)
- 利用 类加载器 把 文件 加载成 class 对象 返回
- 然后你在 .save() 方法时,就可以执行到你的 invoke 方法了,
我的测试代码地址
好了 开始贴代码走流程了(jdk 动态代理怎么实现的 就不 说了,外面博客一大堆)。
1、看一下 动态生成的文件(代码片段,完整代码 戳 上面链接)
/**
动态生成的 代理类。
注意extends Proxy ,
Proxy 中有个 protected InvocationHandler h;
通过h 调用到invoke 方法
代码片段
*/
public final class C$Proxy0 extends Proxy implements TestJDKService {
private static Method m0;
private static Method m1;
private static Method m2;
private static Method m3; // 代理的目标类
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
// 反射
m3 = Class.forName("com.xw.proxy.jdk.TestJDKService").getMethod("save", new Class[]{Class.forName("java.lang.String"), Integer.TYPE});
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
} catch (Throwable e) {
throw new NoSuchMethodError(e.getMessage());
} catch (Throwable e2) {
throw new NoClassDefFoundError(e2.getMessage());
}
}
public final String save(String str, int i) {
RuntimeException e;
try {
//这里 就调到了自己的 MyInvocationHandler 中的 invoke方法了
return (String) this.h.invoke(this, m3, new Object[]{str, Integer.valueOf(i)});
} catch (Error e2) {
e = e2;
throw e;
} catch (RuntimeException e3) {
e = e3;
throw e;
} catch (Throwable th) {
UndeclaredThrowableException undeclaredThrowableException = new UndeclaredThrowableException(th);
}
}
2、解释一下 invoke 中的三个参数,断点跑一下或者看生成的 save() 方法源码就知道了
3、解释一下 Proxy.newProxyInstance() 方法
public <T> T getProxy() {
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
这就是动态生成 class 对象,(实现逻辑:生成java 再反编译,然后把class 读到内存中返回)
唉!jdk 动态代理,结束!
补充一下 动态生成 class 的方式:
通过 io 把 java 代码写到文件里,然后你再编译一下,然后 利用 ClassLoader 读成class 对象返回