Java Jdk Proxy
Contents
分析环境: jdk8
dynamic proxy 是啥?
A dynamic proxy class is a class that implements
a list of interfaces
1 specified atruntime
such that a method invocation through one of the interfaces on an instance of the class will beencoded and dispatched
toanother
object through auniform interface
2.
- 动态代理类生成调用方法如下:
Proxy.newProxyInstance(handler.getClass().getClassLoader(), new Class[]{Dynasty.class},handler);
handler.getClass().getClassLoader()
运行时动态生成的代理类 load 到 jvm 使用的 class loader。new Class[]{Dynasty.class}
运行时动态生成的代理类实现的一系列接口。handler
Invocation Handler 通过 invoke() 来分发方法,包含被实际代理的对象实例。
保存运行时生成的动态代理类
ProxyGenerator.java
/** debugging flag for saving generated class files */
private final static boolean saveGeneratedFiles =
java.security.AccessController.doPrivileged(
new GetBooleanAction(
"sun.misc.ProxyGenerator.saveGeneratedFiles")).booleanValue();
设置 sun.misc.ProxyGenerator.saveGeneratedFiles
System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
运行时生成的动态代理类($Proxy0)分析
运行时生成的动态代理类实例化
$Proxy0 -> Proxy(InvocationHandler h) 由此可见:
- 动态代理类
$Proxy0
实例化时,调用 super classProxy
的构造函数,需要的 InvocationHandler 是实现了该接口的DynastyDynamicProxy
DynastyDynamicProxy
实例化时,构造函数需要的是TangDynasty
这个实际被代理的类。
运行时生成的动态代理类方法
$Proxy0 的命名
// prefix for all proxy class names
private static final String proxyClassNamePrefix = "$Proxy";
// next number to use for generation of unique proxy class names
private static final AtomicLong nextUniqueNumber = new AtomicLong();
$Proxy0#founder
public final String founder() throws {
try {
return (String)super.h.invoke(this, m4, (Object[])null); // super.h.invoke 指的就是 DynastyDynamicProxy.invoke
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
$Proxy0#reviver
public final String reviver() throws {
try {
return (String)super.h.invoke(this, m5, (Object[])null); // super.h.invoke 指的就是 DynastyDynamicProxy.invoke
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
$Proxy0#lastEmperor
public final String lastEmperor() throws {
try {
return (String)super.h.invoke(this, m3, (Object[])null); // super.h.invoke 指的就是 DynastyDynamicProxy.invoke
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
由上可知,
$Proxy0
实现的方法的统一调用入口(uniform interface
) 就是 DynastyDynamicProxy#invoke,也就是 jdk 动态代理必须实现的 InvocationHandler#invoke 方法。
InvocationHandler
接口实现类 DynastyDynamicProxy
分析
public class DynastyDynamicProxy implements InvocationHandler {
// 被代理的对象
private Object delegate;
public DynastyDynamicProxy(Object originalDynamic){
this.delegate = originalDynamic;
}
/**
@param proxy 当前动态代理类 $Proxy0 的实例
@param method 当前动态代理类调用的方法
@param args 当前动态代理类调用的方法的参数
**/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("公元 618 年唐朝建立!");
String res = (String) method.invoke(delegate,args);
System.out.println(method.getName() + " of Tang Dynasty was " + res + "!");
System.out.println("公元 907 年唐朝灭亡!\n");
return res;
}
}
被代理的类 TangDynasty
分析
public class TangDynasty implements Dynasty{
@Override
public String founder() {
return "李渊";
}
@Override
public String reviver() {
return "李隆基";
}
@Override
public String lastEmperor() {
return "李柷";
}
}
- 由
调用栈
可知,最终还是要调用被代理的类
的方法。- 但是可以在执行真正的代理类方法之前,在
InvocationHandler#invoke
中添加实际需要的逻辑。这就是中间层,通过中间层进行逻辑的增强。- 这样看起来就好像被代理对象的逻辑进行了增强。