上文,咱們效仿Spring源碼,完成了解析配置信息的優雅實踐,能夠覆蓋平常開發中絕大多數的情形。可是有時候仍是不夠靈活,好比要求配置鍵前綴一致。
經過實現EnvironmentAware接口,或者注入Environment的bean,使用getProperty()雖然能夠解決配置鍵比較離散、沒有關聯情形下的取值問題。但總要實現接口或者注入bean,不能爲所欲爲,難以掙脫Spring的桎梏。難免意難平,難道就只能帶着鐐銬起舞嗎?java
迴歸語言的層面上來,Java自己具有IO強大的支持。咱們就不能經過IO的方式讀取文件,而後解析成鍵值對的數據結構嗎。
讀取成流再進行解析,感官上不免以爲十分麻煩,解決問題的同時帶來更多新的問題,有悖初衷。其實JDK提供了便捷的Api供你們使用。
ClassLoader除了能夠加載類信息以外,讀取properties文件也是一把好手。getResourceAsStream()支持將配置文件轉化成InputStream。
同時解析過程JDK提供的支持也足夠輕鬆友好,java.util.Properties類中的load()整好可使得輸入流解析成爲鍵值對。如此這般,可謂天時地利人和。spring
The specified stream remains open after this method returns數據結構
這裏必須注意,JDK對load()有如上說明: 此方法返回後,指定的流保持打開狀態。也就是說咱們必須手動關閉流,以避免形成內存浪費。框架
package com.spring.load_properties;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/** * @Author: Raphael */
public class JavaLoadResources {
private static final Properties properties;
static {
properties = new Properties();
try (
InputStream in = ClassLoader.getSystemClassLoader()
.getResourceAsStream("value.properties"))
{
properties.load(in);
} catch (IOException e) {
e.printStackTrace();
}
}
private JavaLoadResources() {}
public static JavaLoadResources getIntance() {
return Loader.INSTANCE.loader;
}
public Properties getProperties() {
return properties;
}
private enum Loader {
INSTANCE;
private JavaLoadResources loader;
private Loader() {
loader = new JavaLoadResources();
}
}
}
複製代碼
可是看到最後,代碼中依然沒有調用流的close(),並且爲何try-catch的結構也有差別?其實這裏是使用了Java 1.7以後提供的try-with-resources語法糖。Java類庫中包含許多必須經過調用close()手動關閉的資源。好比InputStream ,OutputStream。客戶常常忽視關閉資源,其性能結果可想而知。
Java集合框架之父布洛赫在其著做《Effective-Java》中如此論述:工具
try-with-resources版本比原始版本更精簡,更好的可讀性,並且它們提供了更好的診斷。 能夠在 try-with-resources 語句中添加 catch 子句,就像在常規的 try-finally 語句中同樣。這容許你處理異常,而 不會在另外一層嵌套中污染代碼。post
try-with-resources會在執行完try代碼塊後自動關閉資源。前提是你必須實現了Closeable接口。ta是保證資源正確關閉的最佳方式。性能
此外工具類通常設計爲單例模式。 這裏推薦你們使用聲明單一元素的枚舉類的方式實現。這也是布洛赫最爲贊同的實現方式。《Effective-Java》中如此論述:這種方式相似於公共屬性方法,但更簡潔,提供了免費的序列化機制,並提供了針對多個實例化的堅固保證,即便是在複雜的序列化或反射攻擊的狀況下。這種方法可能感受有點不天然,可是單一元素枚舉類一般是實現單例的最佳方式。
注意,若是單例必須繼承 Enum 之外的父類(儘管能夠聲明一個Enum來實現接口),那麼就不能使用這種方法。測試
遍歷輸出,簡單的驗證一下便可this
package com.spring.load_properties;
import java.util.Properties;
import java.util.function.BiConsumer;
public class GetProperties {
/** * @Author: Raphael */
public static void main(String[] args) {
JavaLoadResources intance = JavaLoadResources.getIntance();
Properties properties = intance.getProperties();
BiConsumer console = (k, v) -> {
System.out.print(k + ": ");
System.out.println(v);
};
properties.forEach(console);
}
}
複製代碼
value.properties配置文件信息以下:
徹底符合預期,這樣一來咱們即可以在不依賴Spring的狀況下更加便捷、靈活的獲取配置信息。