静态类因为编译成字节码,直接在虚拟机上运行,少了读取-从字符串读数据等一系列步骤。速度上肯定占有绝对优势。
但设立properties文件的目的,是为了不改动程序而实现配置数据的变化,特设的使 配置数据 和 程序 的一种简易分离机制。 除非这些配置参数永远不变,不然写成静态类对程序只会是一种退化。
如果需要频繁的读properties文件但是又不常修改文件中的属性,可以将properties文件加载到一个起中间作用的静态类中。
自定义CustomPropertyPlaceholderConfigurer 类,继承自PropertyPlaceholderConfigurer 类:
public class CustomPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
/**
* 需要注入的常量类名数组
*/
private String[] configureClasses;
/**
* 是否区分大小写
*/
private boolean lowerCaseKey = false;
@Override
@SuppressWarnings("unchecked")
protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props)
throws BeansException {
super.processProperties(beanFactoryToProcess, props);
if (configureClasses == null) {
return;
}
Map<String, String> propMap = new HashMap<>(props.size());
String key = null;
if (lowerCaseKey) {
// key不区分大小写,所以将所有key转换成小写
for (Enumeration<?> k = props.propertyNames(); k.hasMoreElements(); ) {
key = (String) k.nextElement();
propMap.put(key.toLowerCase(), props.getProperty(key));
}
} else {
// key区分大小写
for (Enumeration<?> k = props.propertyNames(); k.hasMoreElements(); ) {
key = (String) k.nextElement();
propMap.put(key, props.getProperty(key));
}
}
Class c = null;
Field[] fields = null;
String keyStr = null, value = null;
// 遍历多个常量类
for (int i = 0; i < configureClasses.length; i++) {
try {
c = Class.forName(configureClasses[i]);
} catch (ClassNotFoundException e) {
e.printStackTrace();
continue;
}
fields = c.getFields();
// 遍历属性列表,注入到常量字段中
for (int j = 0; fields != null && j < fields.length; j++) {
keyStr = fields[j].getName();
// 判断常量字段是否有属性匹配,不区分大小写。
value = propMap.get(lowerCaseKey ? keyStr.toLowerCase() : key);
if (null != value && value.length() > 0) {
// 从属性中取出字段值,并存到字段中
if (value != null) {
value = value.trim();
fields[j].setAccessible(true);
try {
if (Integer.TYPE.equals(fields[j].getType())) {
fields[j].setInt(null, Integer.parseInt(value));
} else if (Long.TYPE.equals(fields[j].getType())) {
fields[j].setLong(null, Long.parseLong(value));
} else if (Short.TYPE.equals(fields[j].getType())) {
fields[j].setShort(null, Short.parseShort(value));
} else if (Double.TYPE.equals(fields[j].getType())) {
fields[j].setDouble(null, Double.parseDouble(value));
} else if (Float.TYPE.equals(fields[j].getType())) {
fields[j].setFloat(null, Float.parseFloat(value));
} else if (Boolean.TYPE.equals(fields[j].getType())) {
fields[j].setBoolean(null, Boolean.parseBoolean(value));
} else {
fields[j].set(null, value);
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} finally {
fields[j].setAccessible(false);
}
}
}
}
}
}
public String[] getConfigureClasses() {
return configureClasses;
}
public void setConfigureClasses(String[] configureClasses) {
this.configureClasses = configureClasses;
}
public boolean isLowerCaseKey() {
return lowerCaseKey;
}
public void setLowerCaseKey(boolean lowerCaseKey) {
this.lowerCaseKey = lowerCaseKey;
}
}
Spring配置:
<!-- 使用spring提供的PropertyPlaceholderConfigurer读取properties -->
<bean class="com.xxx.xxx.CustomPropertyPlaceholderConfigurer">
<!-- 属性名是 locations,使用子标签<list></list>可以指定多个配置文件,这里指定了一个-->
<property name="locations">
<list>
<value>classpath*:test.properties</value>
</list>
</property>
<property name="configureClasses">
<list>
<value>com.xxx.xxx.cnst.AxxxCnst</value>
<value>com.xxx.xxx.cnst.BxxxCnst</value>
</list>
</property>
<!--是否区分大小写-->
<property name="lowerCaseKey" value="false"/>
<property name="ignoreUnresolvablePlaceholders" value="true"/>
</bean>
在项目启动时(初始化)会将properties文件中的属性读取到静态类(前提是,静态类中有以properties文件中属性key为名的静态常量)中。