App Class Loader

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上運行,就能夠互相不干擾。

相關文章
相關標籤/搜索