2014-03-26 118 views
4

是什麼VSJava資源VS螺紋

Thread.currentThread().getContextClassLoader().getResource("some-resource-file.txt") 

我有src/test下的資源

getClass().getResource("some-resource-file.txt") 

之間的差額/資源&我試圖從單元測試訪問它們。這是一個典型的Maven風格的目錄結構。

我期待雙方的行爲是相同的。但它不是,getClass()。getResource()不會從線程獲取資源,因爲我可以獲取資源。

那麼他們有什麼不同呢?

+2

那麼你看着上下文類加載器是什麼?你的資源在哪裏,你的背景是什麼? (Web應用程序?還有其他什麼?)目前我們還沒有足夠的信息來幫助您? –

+0

更新了問題以提供更多信息 –

+0

您是否按照它們返回的對象查看了'getClass()。getClassLoader()'和'Thread.currentThread()。getContextClassLoader()'的細節? –

回答

2

有一個特殊情況下獲得第一類運行(這就是爲什麼你必須聲明main()方法爲靜態的,以字符串數組作爲參數)。 一旦這個類被加載並且正在運行,將來加載類的嘗試將由類加載器完成。最簡單的是,類加載器創建一個由字符串名稱引用的類體的平面名稱空間。 Java中的每個類都使用自己的類加載器來加載其他類。因此,如果ClassA.class引用ClassB.class,則ClassB需要位於ClassAClassLoader或其父母的類路徑上。

線程上下文ClassLoader是一個特殊的,因爲它是當前正在運行的線程的當前ClassLoader。這在多類加載器環境中很有用。可以從ClassLoader C中的類創建一個對象,然後將其傳遞給ClassLoader D擁有的線程。在這種情況下,如果對象需要加載自己不可用的資源ClassLoader,則該對象需要直接使用Thread.currentThread().getContextClassLoader()

4

假設你正在開發一個圖書館和圖書館罐被放置到Web容器中的類路徑。

現在讓我們假設一個Web應用程序,使用這個庫,部署在容器中。

該webapp將有它自己的類加載器,使用WEB-INF/classes和WEB-INF/lib/*。jar作爲它的類路徑。並且容器,對於每個請求進入您的web應用程序,都會將當前線程類加載器設置爲類路徑的類加載器。

當您的庫代碼使用getClass().getResource()時,它將使用用於加載庫類的類加載器加載資源。因此它將使用容器的類加載器,並因此將使用庫的jar和用於啓動容器的其他庫中的資源。

如果您的庫代碼使用Thread.currentThread().getContextClassLoader()來代替加載資源,它將使用與當前線程關聯的類加載器,並因此從webapp的類加載器加載資源,在WEB-INF/classes中查找資源並在WEB-INF/lib的jar文件中。

後者可以是你想要的。例如,如果你正在設計一個日誌庫(請不要),記錄器將能夠爲每個webapp讀取一個不同的配置文件,而不是讓所有的webapps共享一個配置文件。

關於這兩種方法尋找資源的方式,它們最終都委託給一個ClassLoader來加載資源。但是通過Class加載它會將相對路徑視爲相對於被調用的類,而通過ClassLoader加載它需要一個從包樹根開始的路徑。假設你的類是在包com.foo,然後

MyClass.class.getResource("hello.txt") 

相當於

MyClass.class.getResource("/com/foo/hello.txt") 

,相當於

MyClass.class.getClassLoader().getResource("com/foo/hello.txt");