Java自己是一种设计的很是简单,很是精巧的语言,因此Java背后的原理也很简单,归结起来就是两点:数据库
一、JVM的内存管理app
理解了这一点,全部和对象相关的问题通通都能解决dom
二、JVM Class Loader学习
理解了这一点,全部和Java相关的配置问题,包括各类App Server的配置,应用的发布问题通通都能解决网站
App Class Loader |----- EJB Class Loader |----- Web App Class Loader
若是在App Class Loader级别配置,是全局可见的。若是打包在EJB里面,那么就不会影响到Web Application,反之亦然,若是你在WEB-INF下面放置Hibernate,也不会影响到EJB。放在EJB Class Loader或者放在Web App Class Loader级别主要就是在局部范围内有效,不影响到其它的应用。hibernate
试想,若是在一个Weblogic上面配置多个虚拟域,你使用www.bruce.com域名,开发你的网站,我使用www.fankai.com开发个人网站,那么固然不但愿咱们的Hibernate相互干扰,因此就能够放在 EJB Class Loader级别来配置Hibernate。设计
进一步阐述一下EJB Class Loader的问题:code
先再次强调一下,Hibernate和EJB,和App Server不存在兼容性问题,他们原本就是不相关的东西,就好像JDBC,相信没有人会认为JDBC和EJB不兼容吧,Hibernate也是同样,它只和JDBC驱动,和数据库有兼容性问题,而和EJB,和App Server彻底是不搭界的两回事。凡是认为Hibernate和EJB不兼容的人,实际上是都是由于对EJB学习的不到家,把责任推到Hibernate身上了。xml
我前面提到过Class Loader的层次,这里不重复了,总之咱们先来看看Class Loader的做用范围:对象
((Boot Strap)) Class Loader: load JRE\lib\rt.jar, sunrsasign.jar, charsets.jar, jce.jar, jsse.jar, plugin.jar Ext Class Loader: load JRE\lib\ext目录下的库文件, load JRE\classes目录下的类 App Class Loader: load CLASSPATH变量指定路径下的类
以上的load路径都是写死在JVM的C++源代码里面的,不能改变,详细请见王森的《Java深度历险》
在一个特定的App Server上,Class Loader会继续向下继承,继承的层次会根据不一样的App Server有所不一样,可是确定不会变的就是:
EJB Class Loader: 继承自App Class Loader,继承层次根据App Server有所不一样,一个EJB Class Loader它的load Class的范围仅限于JAR或者EAR范围以内。 Web App Class Loader: 继承自App Class Loader,继承层次根据App Server有所不一样,一个Web App Class Loader: 它的load Class的范围在 WEB-INF\lib下的库文件和WEB-INF\classes目录下的class文件。
Web App Class Loader很好理解,你们毕竟用的不少,App Server上的一个Web Application会建立一个Web App Class Loader的实例去负责load class,因此若是你想让Hibernate只在这个Web Application内生效,把它放到WEB-INF\lib下去就行了。
若是你把Hibernate放到了CLASSPATH变量指定的路径下,而你在WEB-INF\lib也放了一份,那么Web App Class Loader因为load范围所限,它会首先找到WEB-INF\lib下的那份Hibernate,按照它的配置来初始化Hibernate。
若是你把Hibernate放到了CLASSPATH变量指定的路径下,但你在WEB-INF\lib什么都没有放,那么Web App Class Loader因为load范围所限,它根本什么都找不到,因而它把load Hibernate的责任交给上一级的Class Loader,这样直到App Class Loader,它找到了Hibernate,按照它的配置来初始化Hibernate。
EJB Class Loader稍微复杂一点,不那么容易理解。App Server会针对每个EJB包文件建立一个EJB Class Loader的实例,例如:
((Hello Robbin)).jar ((Hello Bruce)).jar
当你把这两个jar发布到App Server上之后,会建立两个EJB Class Loader的实例,分别去load这两个EJB包,好比说:
CLEJB_Robbin是load ((Hello Robbin)).jar的 CLEJB_Bruce是load ((Hello Bruce)).jar的
那么CLEJB_Robbin的load范围就仅仅限于HelloRobbin.jar以内,它load不到HelloRobbin.jar以外的任何文件,固然它也load不到HelloBruce.jar。
说到这里,我相信你们应该已经明白为何EJB规范不容许EJB有IO操做了吧?由于EJB Class Loader根本找不到jar包以外的文件!!!
若是如今你想实现HelloRobbin.jar和HelloBruce.jar的互相调用,那么该怎么办?他们使用了不一样的EJB Class Loader,相互之间是找不到对方的。解决办法就是使用EAR。
如今假设HelloRobbin.jar和HelloBruce.jar都使用了Hibernate,看看该怎么打包和发布:
HelloEJB.ear |------ ((Hello Robbin)).jar |------ ((Hello Bruce)).jar |------ Hibernate2.jar |------ pojo.jar (定义全部的持久对象和hbm文件的jar包) |------ cglib-asm.jar |------ commons-beanutils.jar |------ commons-collections.jar |------ commons-lang.jar |------ commons-logging.jar |------ dom4j.jar |------ odmg.jar |------ log4j.jar |------ jcs.jar |------ hibernate.properties |------ log4j.properties |------ cache.ccf |------ META-INF\application.xml (J2EE规范的要求,定义EAR包里面包括了哪几个EJB)
除此以外,按照EJB规范要求,HelloRobbin.jar和HelloBruce.jar还必须指出调用jar包以外的类库的名称,这须要在jar包的manifest文件中定义:
((Hello Robbin)).jar |------ META-INF\MANIFEST.MF
MANIFEST.MF中必须包括以下一行:
Class-Path: log4j.jar hibernate2.jar cglib-asm.jar commons-beanutils.jar commons-collections.jar commons-lang.jar commons-logging.jar dom4j.jar jcs.jar odmg.jar jcs.jar pojo.jar
这样就OK了,当把HelloEJB.ear发布到App Server上之后,App Server建立一个EJB Class Loader实例load EAR包里面的EJB,再根据EJB的jar包里面的MANIFEST.MF指出的Class-Path去寻找相应的jar包以外的类库。
因此一个EAR包有点相似一个Web Application,EJB Class Loader的load范围也就是EAR范围以内,它load不到EAR以外的文件。除非把Hibernate定义到CLASSPATH指定的路径下,在这种状况下,EJB Class Loader找不到Hibernate,只能交给上一级的Class Loader,最后由App Class Loader找到Hibernate,进行初始化。
因为EAR这样load Class规则,假设Robbin和Bruce都在同一个Weblogic上运行本身的网站,而咱们都不但愿本身的程序里面的Hibernate配置被对方的搞乱掉,那么咱们就能够这样来作:
Robbin's Website:
Robbin.ear |-------- robbin.war (把Web Application打包) |-------- robbin.jar (把开发的EJB打包) |-------- Hibernate2.jar .......................... |-------- META-INF\application.xml
Bruce's Website:
Bruce.ear |-------- bruce.war (把Web Application打包) |-------- bruce.jar (把开发的EJB打包) |-------- Hibernate2.jar .......................... |-------- META-INF\application.xml
这样在同一个App Server上运行,就能够互相不干扰。