Java的dynamic proxy(动态代理)的使用学习(二)
这篇文章看一下如何从proxy里面取出实际对应的handler。可以在前一篇文章讲解的基础上,做一个InjectFieldProxyHandler
:
如上所示,可以看到我们在BasicProxyHandler
的基础上扩展出来InjectFieldProxyHandler
。
在这个InjectFieldProxyHandler
里面,我们添加了metadata
这个field。然后要做的是,在使用proxy的实例的时候,同时也可以取得这里面的metadata
。
我们具体看一下源代码:
package io.alchemystudio.lang.proxy;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 展示如何从proxy里面提取handler。
// 这样就可以在handler里面封装metadata。
public class InjectFieldProxyHandler extends BasicProxyHandler {
public InjectFieldProxyHandler(Object original) {
super(original);
}
// 这个方法取不到。
// 这个用来封装一个`metadata`的field。
private Object metadata;
public Object getMetadata() {
return metadata;
}
public void setMetadata(Object metadata) {
this.metadata = metadata;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(getOriginal(), args); // 直接pass给original的对应method。
}
public static void main(String[] args) {
Foo foo = new FooImpl();
Foo proxy = (Foo) Proxy.newProxyInstance(
InjectFieldProxyHandler.class.getClassLoader(),
new Class[]{Foo.class},
new InjectFieldProxyHandler(foo));
proxy.echo("Hello, world!");
if (Proxy.isProxyClass(proxy.getClass())) {
InjectFieldProxyHandler handler = (InjectFieldProxyHandler) Proxy.getInvocationHandler(proxy);
handler.setMetadata(System.currentTimeMillis());
System.out.println(handler.getMetadata());
}
}
}
可以看到和前一篇文章里面介绍的基础例子不同,这个class里面加了metadata
这个field。并且我们在main()
方法里面提取了它。
main()
方法代码对应的逻辑图如下:
注意上面的代码当中,我们和前一篇文章当中基础的逻辑没什么不同,有区别的地方是最后我们通过Proxy.isProxyClass()
方法来判断某个instance的class是不是proxy class,然后我们会使用Proxy.getInvocationHandler()
方法来从instance当中得到proxy class对应的InvocationHandler
。
因此,我们的proxy class的instance就可以在原始class的基础上扩展了一个叫做metadata
的field,并去实际的操作它。
这篇文章当中的代码在这里:
以上就是proxy的另一种使用方法。