深入理解 jdk 动态代理的实现
来源:互联网 发布:佛山正大数据恢复中心 编辑:程序博客网 时间:2024/05/16 13:01
最近发现,java框架中大量使用了 动态代理。 原来只是会简单的使用,但是今天想深入研究下jdk是如何实现的。
一个比较靠谱的博客:http://www.cnblogs.com/flyoung2008/archive/2013/08/11/3251148.html
至于Proxy 怎么用,在这里就不赘述了。关键是想说说 jdk怎么实现的。
主要想讲讲 这个方法
Proxy.getProxyClass(ClassLoader loader, Class<?>... interfaces)
分几个步骤:
一、初始化接口参数
String[] interfaceNames = new String[interfaces.length]; //用来检查接口是否重复Set interfaceSet = new HashSet();//做一些验证,同时将 interfaceNames 装满for (int i = 0; i < interfaces.length; i++) { String interfaceName = interfaces[i].getName(); Class interfaceClass = null; try {interfaceClass = Class.forName(interfaceName, false, loader); } catch (ClassNotFoundException e) { } if (interfaceClass != interfaces[i]) {throw new IllegalArgumentException( interfaces[i] + " is not visible from class loader"); } //判断是接口 interfaceClass.isInterface()) {throw new IllegalArgumentException( interfaceClass.getName() + " is not an interface"); } //判断接口是否重复 if (interfaceSet.contains(interfaceClass)) {throw new IllegalArgumentException( "repeated interface: " + interfaceClass.getName()); } interfaceSet.add(interfaceClass); //将接口名称装入数组 interfaceNames[i] = interfaceName;}
二、通过类装载器,来找到当前是否有代理类Map的缓存。避免再次创建。 weakHashMap 是jdk 里的弱键map.直接和垃圾回器挂钩
Object key = Arrays.asList(interfaceNames);//通过class loader 来查找或者创建代理类 //loaderToCache 是一个 WeakHashMap() ,专门用来维护 类加载器和对应的代理类缓存Map cache;synchronized (loaderToCache) { cache = (Map) loaderToCache.get(loader); if (cache == null) {cache = new HashMap();loaderToCache.put(loader, cache); }}
三、针对具体的接口名称集合,来找缓存
//主要是从缓存中查找是否代理对象。//如果没有代理类对象,判断是否有别的线程正在生成当前代理独享synchronized (cache) { do { //以接口名称数组为key,从缓存中代理类Object value = cache.get(key);//判断是接口if (value instanceof Reference) { proxyClass = (Class) ((Reference) value).get();}//找到了直接返回if (proxyClass != null) { return proxyClass;} //没找到,pendingGenerationMarker 是一个标记对象,用来表示当前代理对象是否正在产生else if (value == pendingGenerationMarker) { // 代理对象正在生成,线程阻塞。 try {cache.wait(); } catch (InterruptedException e) { } continue;} else {//当前没有代理对象正在创建,标记该接口列表的代理对象正在创建 cache.put(key, pendingGenerationMarker); break;} } while (true);}
四、代理对象名的产生
//针对一些非public 的接口,得到代理类生成的包路径try { String proxyPkg = null;// package to define proxy class in for (int i = 0; i < interfaces.length; i++) {int flags = interfaces[i].getModifiers();if (!Modifier.isPublic(flags)) { String name = interfaces[i].getName(); int n = name.lastIndexOf('.'); String pkg = ((n == -1) ? "" : name.substring(0, n + 1)); if (proxyPkg == null) {proxyPkg = pkg; } else if (!pkg.equals(proxyPkg)) {throw new IllegalArgumentException( "non-public interfaces from different packages"); }} } //如果全部是public 接口 if (proxyPkg == null) {proxyPkg = ""; } {long num;//当前对象代理对象统一数量管理synchronized (nextUniqueNumberLock) { num = nextUniqueNumber++;}//代理对象新的名称String proxyName = proxyPkg + proxyClassNamePrefix + num;
四、最关键的一步,生成代理对象
//通过 ProxyGenerator 得带代理类的class 的二进制数据byte[] proxyClassFile =ProxyGenerator.generateProxyClass( proxyName, interfaces);try {//调用本地方法,然后直接返回 proxyClass = defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length);} catch (ClassFormatError e) { throw new IllegalArgumentException(e.toString());} } proxyClasses.put(proxyClass, null);} finally {//别忘了,最终要释放还要告知别的线程,代理对象创建完毕。 synchronized (cache) {if (proxyClass != null) { cache.put(key, new WeakReference(proxyClass));} else { cache.remove(key);}//通知阻塞线程cache.notifyAll(); }}return proxyClass;
ok,这个最主要的方法讲完了。
想说明下,其实jdk自带的动态代理生成的代理类,无非就是如下格式
public final class ProxySubject(被代理的类) extends Proxy implements interface(接口集合){//自己定义的InvocationHandlerInvocationHandler invocationHandler;//构造方法,public ProxySubject(InvocationHandler invocationHandler){this.invocationHandler = invocationHandler;}//接口的方法public void method{invocationHandler.invoke(this, method(被调用方法对象), null)}}
关键还是通过继承来实现,也就意味着,被代理对象的父对象无法被动态代理。
0 0
- 深入理解 jdk 动态代理的实现
- 深入理解JDK动态代理
- JDK的动态代理实现原理理解
- 深入理解JDK动态代理机制
- 深入理解JAVA JDK动态代理机制
- 深入理解JAVA JDK动态代理机制
- 深入理解JDK动态代理机制
- 源码角度理解JDK动态代理的实现原理
- jdk动态代理的实现
- jdk的动态代理实现
- JDK动态代理的实现
- 关于JDK动态代理的理解
- JDK 动态代理的简单理解
- JDK 动态代理的简单理解
- 关于JDK动态代理的一点理解
- jdk动态代理的初步理解
- JDK动态动态代理和cglib动态代理的实现
- 深入理解Java的动态代理
- 布隆过滤器 序列化与反序列化
- Android应用程序显示欢迎画面并开机自启动
- Kinect for Windows SDK开发入门(五):景深数据处理 下
- 【Leetcode】Path Sum
- 实例阐述浮点数解包运算过程
- 深入理解 jdk 动态代理的实现
- c++模板技术
- 我的第一篇博文
- Cocos2D-x游戏开发之一:场景切换
- MFC (1)CAnimate Control 应用
- 我的第一周作业
- 链表,队列和栈的区别
- C#_为WinForm窗体定义功能快捷键
- 用Javascript获取页面元素的位置/JQUERY对尺寸的定义