更简单的动态代理

来源:互联网 发布:21cake和诺心 知乎 编辑:程序博客网 时间:2024/04/29 18:06

更简单的动态代理

很多情况下我们需要对某个对象进行动态代理,然而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好用请点个星哦~

0 0
原创粉丝点击