java反射之动态代理学习笔记
来源:互联网 发布:变电话号码的软件 编辑:程序博客网 时间:2024/04/30 09:26
下面是我写的一个小demo,先来看代码
package com.csdn.demo;import com.zhang.jian.zhang;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;/** * Created by zhang on 2016/12/16. * 定义Person接口 */interface Person { String say(String name);}/***定义Student接口*/interface Student{ String study(String name);}/** * Created by zhang on 2016/12/16. * 定义User类实现Person 和 Student 接口,重写接口方法 */class User implements Person,Student { public String study(String name) { System.out.println("User正在学习:"+name); return name; } public String say(String name) { System.out.println("Person的say方法:" + name); return name; }}/** * Created by zhang on 2016/12/16. * 定义 嗯... 我管它叫调用处理器 * 这个主要是用到invoke()方法,作用后面详细介绍 */class MyInvocationHandler implements InvocationHandler { Object obj = null;/** * Created by zhang on 2016/12/16. * 这个方法起到了两个作用 * 1、给obj赋值,将被代理类赋值给obj * 2、该方法返回一个 实现了被代理类实现的所有接口 的代理类,或者说它返回一个代理类-->被代理类实现的那些 * 接口-->生成的代理类也都实现了(具体后面介绍) */ public Object blind(Object obj) { this.obj = obj; return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this); }/** * Created by zhang on 2016/12/16. * invoke方法的作用:生成的代理类要重写实现的接口的方法,重写的方法就是来调用这个invoke()方法 */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("进入了invoke方法了!"); Object returnValue = method.invoke(obj, args); return returnValue; }}public class TestProxy { public static void main(String[] args) { User user=new User(); MyInvocationHandler handler = new MyInvocationHandler(); Student personProxy = (Student) handler.blind(user); personProxy.study("Tom"); }}
运行结果:
进入了invoke方法了!User正在学习:TomProcess finished with exit code 0
下面我们来好好分析一下代理类的生成过程
a)调用Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
这条语句生成代理类。
第一个参数:传入被代理类的类类加载器
第二个参数:传入被代理类实现的所有接口
第三个参数:this也就是我们写的那个调用处理器
(如果你对这里有疑虑的话,建议先去看看Class的相关内容:只简单说一下通过Class可以在运行时得到一个类的完整结构)
然后我们点开Proxy的源码文件,发现newProxyInstance方法有如下一条语句 Class<?> cl = getProxyClass(loader, interfaces);
紧接着
Constructor cons = cl.getConstructor(constructorParams); return cons.newInstance(new Object[] { h });
不难看出它是通过getProxyClass(loader,interfaces)//loader是传入的类加载器,interfaces是传入的所有接口---
方法返回了一个实现了所有接口的代理类的Class,即这么个东西Class<T>
,其中T就是代理类。
b)我们继续去看getProxyClass(loader,interfaces)
,发现它用到了一个这样的数据类型 static Map<ClassLodar,Map<List<String>,Object>>
,通过读代码我们发现这是Proxy用来缓存代理类的,ClassLoader不用说了就是类加载器,List<String>
保存的是传入的所有接口的名字,而对应的代理类就保存在Object中。
根据你的传入参数,来判断如果之前已经生成了相应的代理类就直接拿出来返回。
如果没有生成过这样的代理类就调用如下一条语句来生成,并把它缓存起来
//proxyClass就是返回结果,所以Class<T>是通过这个方法生成的 proxyClass = defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length); //好吧,这个方法是这样定义的,是的我们看到了native关键字,说明这个方法的实现并不是用java写的 //~那么进行到这里就先结束了(已经懒得再去找了)因为我们已经完全可以进行一下合理的推断了~ private static native Class defineClass0(ClassLoader loader, String name, byte[] b, int off, int len);
c)到这里我们已经大体知道代理类是如何生成的了,只是一些细节还不清楚,但是通过程序的运行结果我们可以来合理的推断。
- 当我们运行上面程序中的代理类personProxy.study("Tom")
时,执行的是调用处理器的invoke方法
- 在创建代理类的时候我们传入了一个参数this,也就是调用处理器。生成代理类是这样一条语句return cons.newInstance(new Object[] { h });
- 以上两点,说明生成的代理类有一个构造方法,参数就是一个调用处理器的列表,因此我们也可以推断,代理类的方法的实现就是调用了调用处理器的invoke方法,因此我们只要重写invoke方法就是间接实现了代理类的方法。这就是JDK暴露给我们的一个接口。
到了这里我们是不是对AOP面向切面编程有了初步的认识呢?在调用处理器的invoke方法中如果我们在Object returnValue = method.invoke(obj, args);
的上面和下面写点什么东西,是不是就等于在上下两个代码段之间可以动态插入代码了呢?
待更新…
- java反射之动态代理学习笔记
- Java学习笔记之反射的应用-动态代理
- Java学习之反射机制---动态代理
- java学习之路 之 反射机制(动态代理)
- 黑马程序员java学习笔记,反射及动态代理
- java学习笔记13--反射机制与动态代理
- Java的反射机制与动态代理学习笔记
- (54)Java学习笔记——反射 / 动态代理
- Java学习笔记:反射与代理机制(静态、动态)
- java学习笔记之动态代理
- java学习笔记之动态代理
- 反射和动态代理之Java学习总结
- J2SE学习笔记:反射与动态代理
- 笔记:Java反射以及动态代理
- java反射--动态代理学习案例代码
- java学习脚印:反射与动态代理
- Java 反射之JDK动态代理
- JAVA 反射 总结 之 动态代理
- $.getJSON异步请求和同步请求
- The method read(CharBuffer) from the type Reader refers to the missing type CharBuffer
- angular $watch学习(监听数组)
- HTTP中继(代理)、隧道相关介绍及简单Java实现
- IO流之字符流
- java反射之动态代理学习笔记
- SSH工作原理
- 树莓派禁止休眠设置
- IO流之字节流
- 大数据Spark “蘑菇云”行动第100课:Hive性能调优之企业级Join、MapJoin、GroupBy、Count、数据倾斜彻底解密和最佳实践
- codeforce 742 E. Arpa’s overnight party and Mehrdad’s silent entering (分食物||二分图染色+dfs)
- MySql 1130-host ... is not allowed to connect to this MySql server
- 广电发布“中国原创游戏精品出版工程”通知
- 生成试验数据的茎叶图,并显示不同区间数据的个数