上文,咱们效仿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是保证资源正确关闭的最佳方式。性能
这种方式相似于公共属性方法,但更简洁,提供了免费的序列化机制,并提供了针对多个实例化的坚固保证,即便是在复杂的序列化或反射攻击的状况下。这种方法可能感受有点不天然,可是单一元素枚举类一般是实现单例的最佳方式。
注意,若是单例必须继承 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);
}
}
复制代码