动态代理其实就是Java.lang.reflect.Proxy类动态的根据指定的所有接口生成一个class byte,该class会继承Proxy类,并实现所有指定的接口(在参数中传入的接口数组),也就是说,返回的对象可以转换类型为接口数组中的任何一个接口类型。然后再利用第一个参数的classloader将class byte加载进系统,最后生成这样一个类的对象并初始化该对象的一些值,如invocationHandler,则是在参数中传入的第三个参数,以及所有的接口对应的method成员,初始化之后将对象返回给调用的客户端,这样客户端就拿到了一个实现所有接口的Proxy对象
在Proxy.newProxyInstance方法调用时,具体步骤如下
1 根据传入的第二个参数interface数组动态生成类,实现interfaces数组中每个interface的接口方法,并且继承了Proxy类,重写了hashcode,toString,equals等方法,对应的类名称为$Proxy0,这里有一个很重要的点,就是会重写哪些方法,上面已经介绍了包括所有interfacade的接口方法,重写了3个基本Object的方法,所以例如getClass等方法是不会被重写的,可以通过对比动态代理的返回的对象调用toString和getClass方法来测试,前者是会经过代理方法,而后者却不会经过代理方式。
2 通过传入的第一个参数classloader将第一步生成的类加载到jvm中
3 利用第三个参数,调用 P r o x y 0 的 Proxy0的 Proxy0的Proxy0(InvocationHandler)构造方法,创建这个类的实例,并且将invocationHandler对象设置进类实例中,循环所有接口方法,将invocationHandler对象织入实现中,所以调用任何一个接口方法,实际上都是调用的invocationHandler.invoke方法,真正的业务逻辑实际也在invoke里面,通过传入的具体的invocationHandler对象来实现(一般是新建类继承InvocationHandler类,并且将真正的实现者注入进去),至于 P r o x y 0 会 不 会 在 i n v o k e 方 法 的 前 后 加 入 代 码 , 例 如 日 志 , 统 计 等 没 有 具 体 研 究 。 另 外 还 会 生 成 M e t h o d 对 象 , 初 始 化 Proxy0会不会在invoke方法的前后加入代码,例如日志,统计等没有具体研究。另外还会生成Method对象,初始化 Proxy0会不会在invoke方法的前后加入代码,例如日志,统计等没有具体研究。另外还会生成Method对象,初始化Proxy0实例的几个Method成员变量
4 将第三部生成的$Proxy0实例返回给客户端。
摘自
原文:https://blog.youkuaiyun.com/benluobobo/article/details/52232179