如何在编译时使用属性文件创建动态接口?
这里的问题是我们使用的属性文件具有非常大的名称作为密钥,我们大多数人遇到错误的键命名问题。 所以它让我思考是否有办法基于属性文件生成以下接口。 我们对属性文件所做的每个更改都将自动调整Properties接口。 还是有其他解决方案吗?
属性文件
A=Apple B=Bannana C=Cherry
应该生成以下接口
interface Properties{ public static final String A = "A" // keys public static final String B = "B"; public static final String C = "C"; }
在我的应用程序代码中
String a_value = PROP.getString(Properties.A);
有一个关于编程的旧规则,不仅仅是关于它,如果看起来很漂亮,那么很可能它是正确的方法。
从我的观点来看,这种方法看起来不太好。
第一件事:
不要在接口中声明常量。 它违反了封装方法。 请查看这篇文章: http : //en.wikipedia.org/wiki/Constant_interface
第二件事:
使用前缀作为属性的名称部分,这是一些特殊的 ,让我们说: key_
当您加载属性文件时,迭代键并提取名称以key_
开头的键,并使用这些键的值,因为您计划在问题中使用这些常量。
UPDATE
假设,我们使用Apache Ant脚本在编译过程中生成一个巨大的属性文件。
例如,让我们的属性文件( myapp.properties
)看起来像这样:
key_A = Apple key_B = Banana key_C = Cherry anotherPropertyKey1 = blablabla1 anotherPropertyKey2 = blablabla2
我们想要处理的特殊属性的关键名称以key_
前缀开头。
所以,我们编写以下代码(请注意,它没有经过优化,只是概念certificate):
package propertiestest; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; import java.util.Enumeration; import java.util.HashSet; import java.util.Properties; import java.util.Set; public class PropertiesTest { public static void main(String[] args) throws IOException { final String PROPERTIES_FILENAME = "myapp.properties"; SpecialPropertyKeysStore spkStore = new SpecialPropertyKeysStore(PROPERTIES_FILENAME); System.out.println(Arrays.toString(spkStore.getKeysArray())); } } class SpecialPropertyKeysStore { private final Set keys; public SpecialPropertyKeysStore(String propertiesFileName) throws FileNotFoundException, IOException { // prefix of name of a special property key final String KEY_PREFIX = "key_"; Properties propertiesHandler = new Properties(); keys = new HashSet<>(); try (InputStream input = new FileInputStream(propertiesFileName)) { propertiesHandler.load(input); Enumeration> enumeration = propertiesHandler.propertyNames(); while (enumeration.hasMoreElements()) { String key = (String) enumeration.nextElement(); if (key.startsWith(KEY_PREFIX)) { keys.add(key); } } } } public boolean isKeyPresent(String keyName) { return keys.contains(keyName); } public String[] getKeysArray() { String[] strTypeParam = new String[0]; return keys.toArray(strTypeParam); } }
类SpecialPropertyKeysStore
过滤并将所有特殊键收集到其实例中。
您可以获得这些键的数组,或检查键是否存在。
如果您运行此代码,您将获得:
[key_C, key_B, key_A]
它是具有特殊键名的返回数组的字符串表示forms。
根据您的要求更改此代码。
我不会从属性生成类或接口,因为您将失去以下function:
- 记录这些属性,因为它们将由java元素+ javadocs表示
- 引用代码中的那些属性,因为它们将使用旧的java常量,并且编译器将完全了解它们。 重构它们也是可能的,而自动名称是不可能的。
您还可以使用枚举,或创建一些特殊的Property
类,其名称为only和final字段。 然后,您只需要一个get
Properties
, Map
或其他内容的get
方法。
至于您的请求,您可以使用maven-exec-plugin执行代码。
您应该只创建一个读取属性文件的main,以及每个键:
- 将密钥转换为有效的java标识符(您可以使用isJavaIdentifierStart和isJavaIdentifierPart将
_
替换为无效的char) - 使用简单的旧Java编写您的类/接口/任何您喜欢的(并且不要忘记为最终的双引号或反斜杠转义!)
因为它是构建的一部分,比如说在构建依赖于这些常量的其他类之前,我建议你创建一个特定的maven项目来隔离这些构建。
不过,我真的不这样做,并使用加载了任何需要的POJO(CDI,Spring,静态初始化等)。