2012-04-24 32 views
0

我對如何使用maven provided範圍和Java類加載器存在誤解。Maven提供的範圍和Java類加載器

假設我有一個類MyClass,並且此類有一個serialize()方法,該方法使用一個枚舉來描述序列化時要使用的JSON庫。

其中一個JSON庫是內部的,並且包含在我爲MyClass分發的JAR中。簡單。

另一個JSON庫是我想強制用戶提供的第三方庫。因此,我把它放在我的pom下<scope>provided</scope>

一切都在測試過程中對我的作品,但是當我試圖用我自己的庫從外面沒有第三方JSON庫在我的類路徑,我得到ClassNotFoundException S,雖然我不是做一個呼叫serialize()在所有。

我是那類只加載「按需」的假設下,因爲我不是做一個呼叫serialize(),我不應該有任何運行時的問題。我錯了嗎?有沒有辦法實現我在這裏得到的?

回答

0

發現的問題。我有一個靜態初始化程序,它正在調用第三方JSON庫,這是造成這個問題的原因。

我想到一個類沒有發現,如果我的API的用戶以及不提供第三方JAR。但是,我擔心的是我沒有打電話來引起JAR的需要。靜態初始化器把我扔了。

0

提供的範圍基本上意味着它在運行時可用。通常不適用於第三方庫(如JSON)。由於您正在打包自己的jar,因此您需要在其中包含所有必需的類。通常Maven用戶使用類似Maven Assembly Plugin的東西來讓Maven包裝在一起所需的依賴關係並創建一個jar。

0

「設置」意味着,這將是後提供,在運行時,因此不將其包括在依賴關係(例如打包應用程序時到WAR或JAR)

的此當一個很好的例子在編譯時針對API進行編譯,比如Java EE API,在編譯時您需要使用該jar,但不需要將其包含在WAR文件中,因爲服務器將根據定義具有這些類。

您需要servlet類進行編譯,但您的WAR文件將始終用於容器已在類路徑中擁有它的上下文中。

0

首先,您在需要時加載類的假設通常是正確的,但它的工作原理與您的想法完全不同。當需要的時候,Class加載器會和它引用的所有類一起加載。它遞歸地發生。因此,當您第一次使用MyClass時,類加載器會嘗試加載引用的第三方JSON庫類。通過使用Java反射功能,您正在談論的一種運行時類加載是可能的。然而,這是非常不同的事情,你可能已經知道了。

第二件事是在Maven中的provided範圍。它的工作原理與compile一樣,但依賴關係不會與工件「走」。這意味着這種依賴性在編譯時和測試執行時可用(然後由Maven提供)。然而,它不會被看作是神器的傳遞依賴(通過依賴這個神器的神器)。所以它不會被複制到WAR的WEB-INF/lib目錄,這取決於您的工件,也不會被jar-with-dependenciesmaven-assembly-plugin的描述符組裝。這裏有一個強有力的假設,即你的工件的用戶自己提供了這個依賴關係,所以這裏他的業務就是將這些類提供到classpath中。通常,它用於Java EE應用程序服務器,其中一些與平臺相關的依賴項始終可用,如Servlet API,JPA,EJB或JMS。如果您的應用程序使用這些API,那麼您可以使用provided作用域。

所以在最後,你的情況,你應該使用defaut,compile範圍,因爲確實需要這種依賴性。