2012-05-29 23 views
2

我有一個問題,我正在努力。問題是,我甚至不知道我應該在谷歌上搜索什麼,所以這就是爲什麼我要求在這裏對SO進行簡單解釋。具有共同依賴性的多個應用程序的Glassfish環境

假設我有三個項目:A,B和C.A是B和C的依賴項.B和C是Web服務,例如可以在Glassfish中部署的Web服務。在A中,有一個類靜態字段,我們假設一個int。在構建項目B時,static int的值爲3.然後,我們構建項目C,但我們將static int的值更改爲4.

問題是:當我們將B和C都部署到Glassfish時,是否運行這些應用程序在單獨的「環境」中,static int在每個環境中具有不同的值(B的env中的3,C中的env中的4)或者僅存在一個static int? LE:B和C都部署在同一個Glassfish域中。 Glassfish版本是3.1.1。

回答

3
The problem is that I do not even know what exactly I should search for on google, so that's why I am asking for a short explanation here on SO. 

你想要搜索的是「Classloader」。這種類型的對象負責加載Java類。由JVM加載的每個類都由其完全限定名稱加載它的類加載器的實例標識。這意味着在一個單獨的JVM中,可以有幾個名稱完全爲「com.example.Test」的類,每個類都由不同的類加載器加載 - 並且每個類都有自己的靜態字段。更重要的是,這些類在運行時會被認爲是不同的:從一個類加載器將「com.example.Test」轉換爲其他類加載器的「com.example.Test」將以ClassCastException結束。

爲了避免在多次加載多個常用類(如java.util.List)的情況下,類加載器通常保持在乾淨的層次結構中。每個類加載器都知道它的「父類」,即負責加載「更一般類」的類加載器。當我們嘗試加載一個類(通常是「按名稱」發生的),比如「com.example.OtherTest」,當前類加載器試圖詢問它的父代是否能夠加載它(並且父代又要求其父代, 等等)。這樣,每個類都可以加載它的最普通的類加載器(java.lang.String將始終由標準引導類加載器加載,即使其他一些類加載器有一些不同的版本可用)。

當你部署一場戰爭時,glassfish會爲它創建一個單獨的類加載器。類加載器知道如何從WEB-INF/lib和WEB-INF/classes中加載類。它的父代是(或至少是祖父)域加載器,對所有應用程序都是通用的。因此,在應用程序類加載器加載任何類之前,它會要求Glassfish來完成它。整個過程是相當可配置的,並且使您可以只將一個通用庫的副本加載到JVM中(例如,如果將庫放入-AFAIR - domain1/lib/ext中,它們將可用於域類加載器,每個應用程序的類加載器的祖先;或者你甚至可以把它放在你的JRE的lib/ext文件夾中,並讓它可用於主類加載器,它將爲你運行的任何應用程序加載類)。在這種情況下,他們將共享靜態字段。或者你可以通過war classloader加載你的庫,並且讓所有的靜態字段對你的應用程序「私有」。

+0

'或者你可以讓你的庫被war classloader加載,並且讓所有的靜態字段對你的應用程序「私有」。這意味着如果我在兩個不同的'WARs'中將依賴關係打包兩次,那麼不同的類加載器將會使用? (對於一個愚蠢的問題抱歉,但我只是想確定,這個問題已經困擾了我很長一段時間,我想完全理解發生了什麼)。 – alegen

+0

是的。每個Web應用程序都有自己的類加載器;否則應用程序可能會相互「攻擊」。 – fdreger

+0

btw:類加載的次數不取決於罐子的數量。你可以想象同一個類從同一個文件中加載了10次,由不同的類加載器加載。 – fdreger

3

如果「A爲B」和「一種用於C」是不同的,你需要爲B和C創建部署A的每個封閉自己的副本

最簡單的方法是最有可能的一個獨立B的WAR封裝了A_for_B.jar,另外一個用於封裝A_for_C.jar的C的WAR。

+1

這確實是我的情況。對不起,在我最初的問題中沒有提到這一點。它們都被封裝在兩個不同的'WARs'中,一個使用'A_B',另一個使用'A_C'。這是否意味着由於「A」的兩個副本會有兩個「靜態整數」? – alegen

+0

是的,會有兩個A彼此不知道(在glassfish的默認配置中) –

+0

感謝您爲我清除這個! :) – alegen

相關問題