文章目录
- invocationHandler和proxy的关系,为什么一定要用proxy的形式呢
- 方案一 实现类直接调用
- 方案二 调用处理实现类直接调用
- 方案三
- 如何能够看到代理文件呢
- invoke方法自动调用-$Proxy0代码
- 其他
- 文章
上一篇博客概括的做了个笔记,这篇笔记主要记录下invoke自动调用的原理,因为稍微有点绕,也有些内容,所以单独拿出来。
invocationHandler和proxy的关系,为什么一定要用proxy的形式呢
这又是个比较大的话题。
需要看下进化过程。
方案一 实现类直接调用
直接调用,没用到调用处理接口,也没用到proxy。
/* 直接调用 start */
Car car = new Car();
car.run("100米");
/* 直接调用 end */
方案二 调用处理实现类直接调用
用到了调用处理实现类,没用到proxy。
/* invocationHandler调用 start */
Car car = new Car();
TimeInvocationHandler timeInvocationHandler = new TimeInvocationHandler(car);
String[] arg2={"100米"};
try {timeInvocationHandler.invoke(null,Car.class.getMethod("run",String.class),arg2);
} catch (Throwable e) {e.printStackTrace();
}
/* invocationHandler调用 end */
方案三
用到了调用处理实现类,也用到了proxy。
/* proxy调用 start */
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
Car car = new Car();
TimeInvocationHandler timeInvocationHandler = new TimeInvocationHandler(car);
Object o
=Proxy.newProxyInstance(Car.class.getClassLoader(),new Class[]{Vehicle.class},timeInvocationHandler);
Vehicle proxyInstance = (Vehicle)o;
proxyInstance.run("100米");
/* proxy调用 end */
如何能够看到代理文件呢
执行前加上这一行代码:
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
这样就会生成该class文件,com.sun.proxy.$Proxy0。
invoke方法自动调用-$Proxy0代码
看到代码就一目了然了,原来是$Proxy0实现了业务接口,调用run()方法的时候,再反调h.invoke()。
这种机制也不难理解,至于为什么用这种形式实现,直接调用方法不好吗?
主要是这种机制实现了动态代理。
如下代码包名等,个别有省略,补全下即可。
package com.sun.proxy;public final class $Proxy0 extends Proxy implements Vehicle {private static Method m1;private static Method m2;private static Method m3;private static Method m0;public $Proxy0(InvocationHandler var1) throws {super(var1);}public final boolean equals(Object var1) throws {try {return (Boolean)super.h.invoke(this, m1, new Object[]{var1});} catch (RuntimeException | Error var3) {throw var3;} catch (Throwable var4) {throw new UndeclaredThrowableException(var4);}}public final String toString() throws {try {return (String)super.h.invoke(this, m2, (Object[])null);} catch (RuntimeException | Error var2) {throw var2;} catch (Throwable var3) {throw new UndeclaredThrowableException(var3);}}public final void run(String var1) throws {try {super.h.invoke(this, m3, new Object[]{var1});} catch (RuntimeException | Error var3) {throw var3;} catch (Throwable var4) {throw new UndeclaredThrowableException(var4);}}public final int hashCode() throws {try {return (Integer)super.h.invoke(this, m0, (Object[])null);} catch (RuntimeException | Error var2) {throw var2;} catch (Throwable var3) {throw new UndeclaredThrowableException(var3);}}static {try {m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));m2 = Class.forName("java.lang.Object").getMethod("toString");
// 这里的包名改下m3 = Class.forName("com.test.Vehicle").getMethod("run", Class.forName("java.lang.String"));m0 = Class.forName("java.lang.Object").getMethod("hashCode");} catch (NoSuchMethodException var2) {throw new NoSuchMethodError(var2.getMessage());} catch (ClassNotFoundException var3) {throw new NoClassDefFoundError(var3.getMessage());}}
}
其他
文章
jdk动态代理介绍及invoke方法自动运行的原因 # 这篇不错,说的比较清楚