您当前位置:首页 > 资源优势 > 平台资源 >

平台资源

java程序员面试必备知识:java的动态代理

发布时间:06-16    点击数:

在讲动态代理之前,需要了解什么是代理模式,经典的代理模式的uml图相信大家都见过:

代理模式

RealSubject是需要被代理的对象。我们要在RealSubject之外增加一些处理,就增加一个Proxy类,实现Subject接口,在Proxy类里持有RealSubject的实例。

Client的请求全部打到Proxy实例上,由Proxy实例来控制是否将请求转发给RealSubject,或者做额外的处理。

代理模式的优点:对于外界来讲,完全无感知,耦合性低。

看一下实例代码:

这里对Integer类做了一层代理。这个类的作用在于,在compareTo请求之上增加了信息的打印输出。

在实际场景中,如果我们需要对多个方法都要做类似的处理,在每个地方都增加同样的代码,就显得有点不够优雅了。这时候,可以使用java的动态代理。

常用的动态代理有两种实现方式:JDK和CGLIBJDK动态代理

看名字就可以知道,这种动态代理是JDK本身就支持的,需要借助java.lang.reflect下的接口来实现。

创建代理对象

要想创建一个代理对象,需要使用Proxy类的newProxyInstance方法。

java程序员面试必备知识:java的动态代理

这个方法有三个参数:类加载器。作为Java安全模型的一部分,对于系统类和从因特网上下载下来的类,可以使用不同的类加载器。Class对象数组,每个元素都是需要实现的接口。调用处理器。

调用处理器

调用处理器是实现了InvocationHandler接口的类对象。在这个接口中只有一个方法:

动态代理类,需要实现此接口,在接口方法的实现里做代理逻辑的处理。

创建动态代理

创建一个动态代理对象的工作如下:获取 RealSubject上的所有接口列表;确定要生成的代理类的类名,默认为:com.sun.proxy.$ProxyXXXX ;

根据需要实现的接口信息,在代码中动态创建 该Proxy类的字节码;

4 将对应的字节码转换为对应的class 对象;创建InvocationHandler 实例handler,用来处理Proxy所有方法调用;

Proxy的class对象以创建的handler对象为参数,实例化一个proxy对象。

接下来我们看一段代码实现:

那如何TraceHandler有什么用呢?

利用TraceHandler可以打印出二分查找的查找顺序:

为何toString也会被代理

细心的读者会发现,上面的程序执行最后有一行

为什么toString方法也会被代理呢,我们代理的接口里,并没有声明toString的方法呀。

这里有两点我们需要知道:所有的代理类都扩展于Proxy类;

所有的代理类都覆盖了Object类中的方法toString、equals和hashCode;

针对上面的第二点,所有对代理类的toString、equals和hashCode的方法调用,都会请求到invoke代理实现上去。所以就出现toString方法也被代理的情况了。

上一篇:谈谈 Java 反射机制,动态代理是基于什么原理?
下一篇:坑爹!花费2亿耗时2年,网站没建完Java都写不好,顶级咨询公司埃森哲被告上法庭