1. 程式人生 > >java讀取配置文件的推薦方法getResource、getResourceAsStream

java讀取配置文件的推薦方法getResource、getResourceAsStream

blog 雙親委派 無法 gets asstream 配置文件 java.net 部分 dia

在java開發中經常會讀取配置文件,如果把文件路徑寫死,就太LOW了,也不符合編碼規範。

在網上找了一些資料後,發現有兩種方法:xxx.class.getResource("") xxx.class.getClassLoader().getResource("")

1.先看一個例子:

技術分享圖片

其實,class.getResource("/") == class.getClassLoader().getResource(""),

Class.getResource和ClassLoader.getResource本質上是一樣的,都是使用ClassLoader.getResource加載資源的。

對於Class.getResource:

先獲取文件的路徑path,不以‘/‘開頭時,默認是從此類所在的包下取資源;path以‘/‘開頭時,則是從項目的ClassPath根下獲取資源。

對於ClassLoader.getResource:

同樣先獲取文件的路徑,path不以‘/‘開頭時,首先通過雙親委派機制,使用的逐級向上委托的形式加載的,最後發現雙親沒有加載到文件,最後通過當前類加載classpath根下資源文件。

對於getResource("/"),‘/‘表示Boot ClassLoader中的加載範圍,因為這個類加載器是C++實現的,所以加載範圍為null。

2.以上兩種方法返回的都是 java.net.URL對象,如果需要得到相應的String類型,可以用以下方法:

xxx.class.getResource("").getPath();

xxx.class.getResource("").getFile();

或者通過 InputStream input = getClass().getClassLoader().getResourceAsStream("config\\config.properties"); 獲取IO流,讓其它方法調用。

註:getResourceAsStream()的路徑同getResource

3.下面講下getPath() 和 getFile()的區別:

技術分享圖片

返回的結果:

url.getFile()=/pub/files/foobar.txt?id=123456

url.getPath()=/pub/files/foobar.txt

4.類加載器ClassLoader

我們都知道 Java 文件被運行,第一步,需要通過 javac 編譯器編譯為 class 文件;第二步,JVM 運行 class 文件,實現跨平臺。

而 JVM 虛擬機第一步肯定是 加載 class 文件,所以,類加載器實現的就是(來自《深入理解Java虛擬機》):

通過一個類的全限定名來獲取描述此類的二進制字節流

類加載器有幾個重要的特性:

(1) 每個類加載器都有自己的預定義的搜索範圍,用來加載 class 文件;

(2) 每個類和加載它的類加載器共同確定了這個類的唯一性,也就是說如果一個 class 文件被不同的類加載器加載到了 JVM 中,

那麽這兩個類就是不同的類,雖然他們都來自同一份 class 文件;

(3) 雙親委派模型

4.1 雙親委派模型

(1) 所有的類加載器都是有層級結構的,每個類加載器都有一個父類類加載器(通過組合實現,而不是繼承),除了啟動類加載器(Bootstrap ClassLoader)

(2) 當一個類加載器接收到一個類加載請求時,首先將這個請求委派給它的父加載器去加載,所以每個類加載請求最終都會傳遞到頂層的啟動類加載器,如果父加載器無法加載時,子類加載器才會去嘗試自己去加載;

通過雙親委派模型就實現了類加載器的三個特性:

委派(delegation):子類加載器委派給父類加載器加載;

可見性(visibility):子類加載器可訪問父類加載器加載的類,父類不能訪問子類加載器加載的類;

唯一性(uniqueness):可保證每個類只被加載一次,比如 Object 類是被 Bootstrap ClassLoader 加載的,因為有了雙親委派模型,所有的 Object 類加載請求都委派到了 Bootstrap ClassLoader,所以保證了只被加載一次。

4.2 Java 中的類加載器

從 JVM 虛擬機的角度來看,只存在兩種不同的類加載器:

(1) 啟動類加載器(Bootstrap ClassLoader),是虛擬機自身的一部分;

(2) 所有其他的類加載器,獨立於虛擬機外部,都繼承自抽象類 java.lang.ClassLoader

而絕大多數 Java 應用都會用到如下 3 中系統提供的類加載器:

(1) 啟動類加載器(Bootstrap/Primordial/NULL ClassLoader):頂層的類加載器,沒有父類加載器。負責加載 /lib 目錄下的,或則被 -Xbootclasspath 參數所指定路徑中的,

並被 JVM 識別的(僅按文件名識別,如 rt.jar,名字不符合的類庫即使放在 lib 目錄也不會被加載)類庫加載到虛擬機內存中。所有被 Bootstrap classloader 加載的類,

它的 Class.getClassLoader 方法返回的都是 null,所以也稱作 NULL ClassLoader。

(2) 擴展類加載器(Extension CLassLoader):由 sun.misc.Launcher$ExtClassLoader 實現,負責加載 <JAVA_HOME>/lib/ext 目錄下,或被 java.ext.dirs 系統變量所指定的目錄下的所有類庫;

(3) 應用程序類加載器(Application/System ClassLoader):由 sun.misc.Launcher$AppClassLoader 實現。它是 ClassLoader.getSystemClassLoader() 方法的默認返回值,

所以也稱為系統類加載器(System ClassLoader)。它負責加載 classpath 下所指定的類庫,如果應用程序沒有自定義過自己的類加載器,一般情況下這個就是程序中默認的類加載器。

如下,就是 Java 程序中的類加載器層級結構圖:

技術分享圖片

參考:https://blog.csdn.net/zhangshk_/article/details/82704010

java讀取配置文件的推薦方法getResource、getResourceAsStream