什么是动态代理
动态代理就是在运行时生成动态的代理对象,静态代理是通过接口,封装来实现对特定对象的代理,而动态代理则可以在运行时通过反射或者字节码来动态生成代理对象,而不仅仅只针对于特定对象。
动态代理分为两种: JDK动态代理和Cglib动态代理,前者是通过反射实现,后者是通过字节码实现,这篇博客主要讲解JDK动态代理的基本原理。
我们知道,在静态代理中,我们的代理类需要实现和被代理对象相同的接口并且聚合该代理对象,在实现重写接口方法的时候调用本身聚合的对象的实现方法从而来解决代理问题。
在JDK动态代理中,其实思想和静态代理差不多,最重要的区别只是JDK动态代理通过反射来实现静态代理,是静态模式动态化。
使用例子
1 | public interface Hello { |
源码浅析
我们要阅读源码首先要知道整个流程大概干了什么。
我们先从使用中来猜测,我们实现了自己的InvocationHandler,这个Handler中有一个target字段,这个target指的就是被代理对象(即目标类),在被重写的invoke方法中我们通过method和args来调用target的与之对应的方法,并且在整个invoke方法中我们对它做了一些增加(即代理方法)。
我们还可以发现,我们的HelloImpl被代理类需要实现一个接口,这也是JDK动态代理的要求,毕竟它是通过接口来实现的。
在客户端主方法中我们new了一个HelloImpl对象然后将这个对象传入自己实现的InvocationHandler中,最后通过Proxy类中的newProxyInstance方法来获取代理对象,我们可以发现代理对象也是实现了Hello接口的,这和我们静态代理的实现方法是一样的!
我们再来看一下newProxyInstance方法中的三个参数。
首先第一个是ClassLoader这个就是指当前加载该类的类加载器,第二个是该类实现的接口,第三个就是handler。
最容易理解的就是handler,因为我们具体代理逻辑是写在handler中的,所以肯定要传。而interfaces是因为整个JDK动态代理需要接口的支持,我们暂且不管,这个需要后面有个整体观念。而第一个类加载器是为什么,具体用来做什么?
其实JDK动态代理就是通过传入handler和接口来通过反射来编写代理类的.java文件,然后通过编译器进行编译,最后通过类加载器load进内存。这样三个参数的作用就明了了
动态代理做主要的就是那个newProxyInstance我们首先来看一下这个类具体做了什么。
1 |
|
我们再来看一下getProxyClass0方法。
1 | // 这个方法传入类加载器和接口 |
我们来看一下ProxyClassFactory
1 | private static final class ProxyClassFactory |
我们来看一下生成的字节码文件
1 | // 1、所有JDK动态代理 都是Proxy的子类 且自己是final类 |