更简单的动态代理
很多情况下我们需要对某个对象进行动态代理,然而JDK的代理非常繁琐
大部分情况会写成这样:
Proxy.newProxyInstance(
toProxy.getClass().getClassLoader()
, toProxy.getClass().getInterfaces()
,handler);
。
有一种封装方式大家都知道,省略classloader参数,并把interfaces参数换成要代理的对象。比如这样:
<T> T proxy(InvocationHandler handler, T toProxy) {
return (T)
Proxy.
newProxyInstance(
toProxy.getClass().getClassLoader(),
toProxy.getClass().getInterfaces(),
handler);
}
但是本文不研究这种封装。
继续简化
如果你仅仅需要对某些方法进行封装,也许你会在InvocationHandler中写大量的
if(method.getName().equals(...)){...}
而且代码很不好看。如果能够写成这样会不会更好呢?
new ProxyHandler(toProxy){
ReturnType0 methodName0(T0 arg0, T1 arg1, ...){...}
ReturnType1 methodName1(T0 arg0, T1 arg1, ...){...}
}
举个例子,对于List的get方法,现在需要在调用get前输出
before get invoked with arg0: + index
在get后输出
after get invoked with res: + 结果
你可以这么做:
List<String> listProxy
= proxy(new ProxyHandler<List<String>>(list) {
@SuppressWarnings("unused")
String get(int index) {
System.out.println("before get invoked with arg0:" + index);
String res = toProxy.get(index);
System.out.println("after get invoked with res:" + res);
return res;
}
});
由于匿名类内部并没有直接调用get函数,所以会出现unused警告,使用注解suppress它即可。
代码非常简洁,从定义上完全与List中的方法相同。
如何实现?
非常简单。在调用时,获取proxyhandler中对应名称和参数的方法,如果找不到,则直接调用原对象方法。如果找到,则调用proxyhandler对象的方法。
注意,不能直接method.invoke(proxyhandler,args….),因为虽然定义一致,但本身它们是两种方法。
有没有直接可以用的代码呢?
Style工具集(在版本 1.0.2 或以上 )提供这种实现方式。
https://github.com/wkgcass/Style
调用Style.proxy(proxyHandler)即可。
Style要求 JDK1.8 或以上
您可以参考源代码或者大致思路自行实现它
如果觉得Style好用请点个星哦~