动态代理介绍
不再赘述,用代码再体现下
1 | public class ClientProxy { |
从上述代码基本可以看出动态代理使用Proxy.newProxyInstance()返回被代理的类实例。在利用反射机制执行实例方法时,可以在执行前后增加自定义的逻辑(切面)。
Proxy.newProxyInstance()
既然后续业务调用的都是这玩意儿生成的对象,那么我们来看下这个的源码。这里就只摘抄核心源码。
1 | public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException{ |
通过上述代码我们可以知道,newProxyInstance主要干的事就是用getProxyClass0获取了个Class,然后用反射实例化它,最后返回给我们用。
getProxyClass0()
其实我们用的class是getProxClass0(loader, intfs)生成的用于创建类的二进制数据。这个二进制数据可以想象为java类文件经过编译后生成的.class。这里就不分析getProxClass0怎么生成,反正我看不懂。下面我们重点关注这伙到底生成的啥。我们用下述方法将二进制数据抽成文件,并用使用jd-gui看看其内容。
1 | public static void main(String[] args) { |
getProxClass0生成的$Proxy0.class文件的内容:
1 | public final class $Proxy0 extends Proxy implements IClient { |
嗒哒~其实我们实际使用的类是这个。这里需要注意这几点:
- 该类的构造函数主要就是向父类Proxy传实现InvocationHandler接口的类实例,就是ProxyGenerator.generateProxyClass中的第三个参数。
- 这个类不但实现了接口定义的方法,同时也实现了且仅仅实现了Object的equles,toString,hashCode方法。
- 每个方法的实现基本都是super.h.invoke(this, m3, (Object[])null),调用InvocationHandler的invoke方法,在本例用lambda实现了这个接口方法,功能是打印“before”和“after”
- 这也解决的我困惑已久的问题,即InvocationHandler的invoke方法中的第一个参数proxy:Object到底传入的是啥,从源码中可以知道它就是getProxClass0生成的$Proxy0.class,其实没啥大用处。
打完收工。
Gitalking ...