TOC
相对于Jboss之前的版本,AS7的类加载机制完全不同,AS7的类加载是基于JBoss模块来设计,关于JBoss模块的介绍,可以看上一篇文章Jboss模块介绍
隐式模块依赖
当你部署一个应用到Jboss容器的时候,有些依赖是隐式被加载的,例如如果部署一个Java EE的应用,包含EJBs,因为EJBs需要用到Javax.ejb.* 的包和其他一些Java EE API 相关包,包含这些包的Jar已经预先被制作成Module并且默认包含在容器里头作为JBoss AS的一部分,那么这些Jar的模块将会被自动加载。
那么隐式模块依赖是什么时候被加载的呢?当一个应用部署到容器里头,会经过一条叫做“deployment processors”的链。这条链上的每个processor都有方法去检测这个应用是否需要隐式加载一些模块,如果是,就将相关的依赖加载进来。
检测手段可以有多种,譬如Annotation。如果一个类添加了@Stateless声明,那么容器就知道,这是一个EJB的类。
Jboss AS7隐式加载的模块列表看这里:隐式加载的模块
类加载的优先级
类加载的先后顺序是为了避免类冲突,以下顺序按优先级从高到低排列:
- 系统依赖 - 就是上面说的隐式依赖。
- 用户依赖 - jboss-deployment-structure.xml里头定义的依赖;Manifest文件里通过Dependencies定义的依赖;Class-Path定义的依赖都属于用户依赖。
- 本地资源 - 就是打包在应用里头的类,包括WEB-INF/classes底下的类文件,WEB-INF/lib底下的Jar包
- 内部部署依赖 - 一个部署依赖于另一个部署;譬如一个EAR依赖另一个应用部署,EAR包lib底下的类等。
WAR包的类加载
一个WAR包作为一个单独的module,因此一个WAR包对应一个单独的class loader。
EAR包的类加载
EAR被看作为多module的部署。一般来说,EAR/lib这个文件夹会作为一个module,每一个WAR 或者EJB Jar包作为一个独立的module看待。子模块(WARs和EJB-Jars)一般来说会依赖父模块(EAR/lib),因此子模块可以访问EAR/lib底下的Jar,但子模块之间就不一定可见。可以通过ear-subdeployments-isolated来设置可见性。
<subsystem xmlns="urn:jboss:domain:ee:1.0" >
<ear-subdeployments-isolated>false</ear-subdeployments-isolated>
</subsystem>
默认值是false的,因此一个子模块可以访问另一个子模块的类。
譬如有下面的EAR包结构:
myapp.ear
|
|--- web.war
|
|--- ejb1.jar
|
|--- ejb2.jar
如果ear-subdeployments-isolated设置为false,那么web.war就可以访问ejb1.jar或者ejb2.jar里面的类,同理,ejb1.jar 跟ejb2.jar也是相互可见的。但是这个参数对具有单独类加载器的子部署是不生效的,譬如说EAR中的WAR包,因为每个WAR包是一个字部署,拥有独立的类加载器,因此WAR包之间的类是不可见的。同理,EAR底下Jar包的类也不能访问WAR包里的类。