我对ant
和属性有这种奇怪的行为,我想知道你是怎么想的。我不明白其中的逻辑。这个行为可能是有用的,但我想知道我是否可以依赖它,或者这是一个错误。
看起来ant在展开属性的右侧时应用了前缀,如果没有所需名称的属性。这是SSCCE:
的build . properties:
a=A
formula=${a}
build . xml:
<project default="test">
<target name="test">
<property name="test.a" value="[test.a has been used instead of a, why? prefixValues is false]" />
<property file="build.properties" prefix="test" prefixValues="false" />
<echo>${test.formula}</echo>
</target>
</project>
输出:test:
[echo] [test.a has been used instead of a, why? prefixValues is false]
BUILD SUCCESSFUL
Total time: 364 milliseconds
如您所见,测试。公式应该用"a"而不是"test"。"但是"从来没有定义过。这是原因吗? 的确,这看起来很奇怪。我认为输出应该是${a}
我做了一些测试,我注意到:
如果您在build.xml
中定义a
而不是build.properties
:它按预期工作。即使用以下build.xml
:
<project default="test">
<target name="test">
<property name="a" value="A" />
<property file="build.properties" prefix="test" prefixValues="false" />
<echo>${test.formula}</echo>
</target>
</project>
和build.properties
formula=${a}
输出
A
但是,如果您更改为prefixValues="true"
,输出是:
${a}
when I was expected: ${test.a}
最后,如果您在build.xml中定义<property name="test.a" value="some value" />
(总是使用prefixValues="true"
):输出现在是(如预期的)
some value
所以,我的结论:
prefixValues可以正常工作,只要在右侧使用的属性没有在同一属性文件中定义。
prefixValues对于在右侧和在同一属性文件中定义的属性被忽略。
看一下Ant代码,在属性相关的类中,关于org.apache.tools.ant.property.ResolvePropertyMap
类:
public void resolveAllProperties(Map<String, Object> map, String prefix,
boolean prefixValues) {
// The map, prefix and prefixValues flag get used in the
// getProperty callback
this.map = map;
this.prefix = prefix;
this.prefixValues = prefixValues;
for (String key : map.keySet()) {
expandingLHS = true;
Object result = getProperty(key);
String value = result == null ? "" : result.toString();
map.put(key, value);
}
然后,在getProperty(String)
方法(代码片段)中:
// If the property we are looking up is a key in the map
// (first call into this method from resolveAllProperties)
// or we've been asked to prefix the value side (later
// recursive calls via the GetProperty interface) the
// prefix must be prepended when looking up the property
// outside of the map.
String fullKey = name;
if (prefix != null && (expandingLHS || prefixValues)) {
fullKey = prefix + name;
}
因此,正如您所看到的,如果属性存在于属性文件中,即使prefixValues
为假,它也将接收前缀。
我又做了一些测试,可以得到很多不同的结果。
检查源代码后,我认为在通过文件添加属性时查找属性存在错误。通过修改一些ant源代码,我可以让它工作。
最后,我决定在bug报告(https://issues.apache.org/bugzilla/show_bug.cgi?id=54769)中添加一个建议的补丁。
这是因为属性是不可变的。一旦设置好,它们就会在接下来的构建中保持这种状态。请查看Ant手册中的"property"文档。对于一些人来说,这实际上是一个问题,所以ant-contrib的家伙包括了一个新的任务来模拟一个变量。
如果你像这样改变你的构建:
<project default="test">
<target name="test">
<property file="build.properties" prefix="test" prefixValues="false" />
<property name="test.a" value="[test.a has been used instead of a, why? prefixValues is false]" />
<echo>${test.formula}</echo>
</target>
</project>
你在控制台上得到'A'。这是因为测试。A和测试。在您的新(忽略)赋值给'test.a'