java编程中极限考验是classloader机制的掌握和灵活运用,特别是在复杂的系统,如存在动态类装载,reflect,ejb,aop等环境。
class.forname()
和thread.currentthread().getcontextclassloader())
是否一样?
在很多文章中,都认为两者是一致的,如java研究组织中一篇文章,被我从google搜索到的:
http://www.javaresearch.org/article/showarticle.jsp?column=31&thread=10178
文中说"这个方法可以用class.forname()代替",在一般简单情况是可以替代,但实际上有时候是不能替代的。
classloader存在下面问题:
在一个jvm中可能存在多个classloader,每个classloader拥有自己的namespace。一个classloader只能拥有一个class对象类型的实例,但是不同的classloader可能拥有相同的class对象实例,这时可能产生致命的问题。如classloadera,装载了类a的类型实例a1,而classloaderb,也装载了类a的对象实例a2。逻辑上讲a1=a2,但是由于a1和a2来自于不同的classloader,它们实际上是完全不同的,如果a中定义了一个静态变量c,则c在不同的classloader中的值是不同的。
因此,研究jboss的classloader策略,对于更好地实现ejb组件拼装是用好处的,因为,一个项目中可能要用其他项目的ejb组件,如何实现运行时ejb组件共享,如何实现ejb组件打包是很重要的。
为了说明classloader对于复杂架构是至重关键,列举开源portal产品exo中servivesmanager类内容。
该类是exo利用picocontainer实现功能性service javabeans初始化,在将那些service性质的javabeans加载到pico中时,需要使用到classloader,
exo专门设立一个servicecontext类:
|
在servicesmanager中,有:
private classloader updatedclassloader;
它的初始值是:
thread.currentthread().getcontextclassloader();
如果,这里写class.forname 那么简单,那么你头疼去吧。
但是这样不够:
在addservice方法中,根据加入的不同servicecontext实现类装载:
|
其实向picocontainer中加入一个服务很简单,上述方法的主要代码是处理classloader,考虑到classloader有嵌套关系,上述代码小心使用这个service服务的父classloader,使用父classloader装载服务service。
闽公网安备 35060202000074号