技术开发 频道

Java动态代理机制综合分析及扩展

  代码是最好的老师

  机制和特点都介绍过了,接下来让我们通过源代码来了解一下Proxy到底是如何实现的。首先记住Proxy的几个重要的静态变量:

清单5.Proxy的重要静态变量
  
//映射表:用于维护类装载器对象到其对应的代理类缓存  
privatestaticMaploaderToCache=newWeakHashMap();
  
//标记:用于标记一个动态代理类正在被创建中  
privatestaticObjectpendingGenerationMarker=newObject();
  
//同步表:记录已经被创建的动态代理类类型,主要被方法isProxyClass进行相关的判断  
privatestaticMapproxyClasses=Collections.synchronizedMap(newWeakHashMap());
  
//关联的调用处理器引用  
protectedInvocationHandlerh;

  然后,来看一下Proxy的构造方法:

清单6.Proxy构造方法
  
//由于Proxy内部从不直接调用构造函数,所以private类型意味着禁止任何调用
  privateProxy(){}
  
//由于Proxy内部从不直接调用构造函数,所以protected意味着只有子类可以调用
  protectedProxy(InvocationHandlerh){this.h=h;}

  接着,可以快速浏览一下newProxyInstance方法,因为其相当简单:

清单7.Proxy静态方法newProxyInstance  
publicstaticObjectnewProxyInstance(ClassLoaderloader,
  Class
<?>[]interfaces,
  InvocationHandlerh)  throwsIllegalArgumentException{
  
//检查h不为空,否则抛异常
  if(h==null){
  thrownewNullPointerException();
  }
  
//获得与制定类装载器和一组接口相关的代理类类型对象
  Classcl=getProxyClass(loader,interfaces);
  
//通过反射获取构造函数对象并生成代理类实例
  try{
  Constructorcons
=cl.getConstructor(constructorParams);
  
return(Object)cons.newInstance(newObject[]{h});
  }
catch
(NoSuchMethodExceptione){thrownewInternalError(e.toString());
  }
catch
(IllegalAccessExceptione){thrownewInternalError(e.toString());
  }
catch
(InstantiationExceptione){thrownewInternalError(e.toString());
 
}catch
(InvocationTargetExceptione){thrownewInternalError(e.toString());
  }
  }

  由此可见,动态代理真正的关键是在getProxyClass方法,该方法负责为一组接口动态地生成代理类类型对象。在该方法内部,您将能看到Proxy内的各路英雄(静态变量)悉数登场。有点迫不及待了么?那就让我们一起走进Proxy最最神秘的殿堂去欣赏一番吧。该方法总共可以分为四个步骤:

  对这组接口进行一定程度的安全检查,包括检查接口类对象是否对类装载器可见并且与类装载器所能识别的接口类对象是完全相同的,还会检查确保是interface类型而不是class类型。这个步骤通过一个循环来完成,检查通过后将会得到一个包含所有接口名称的字符串数组,记为String[]interfaceNames。总体上这部分实现比较直观,所以略去大部分代码,仅保留留如何判断某类或接口是否对特定类装载器可见的相关代码。

清单8.通过Class.forName方法判接口的可见性
  
try{
  
//指定接口名字、类装载器对象,同时制定initializeBoolean为false表示无须初始化类
  
//如果方法返回正常这表示可见,否则会抛出ClassNotFoundException异常表示不可见  
interfaceClass=Class.forName(interfaceName,false,loader);
  }
catch(ClassNotFoundExceptione){  }
0
相关文章