严格回答你的问题是,
${project.parent.name}会 不会被解析为部分型号插值处理。反过来,您
StackOverflowError在代码的完全不同的位置有一个,即何时…构建项目的最终JAR。
第1部分:建立的模型是错误的
这是发生了什么。在项目上启动Maven命令时,它要执行的第一步是创建项目的有效模型。这意味着读取您的POM文件,使用激活的配置文件进行推理,应用继承,对属性进行插值…所有这些都为您的项目构建了最终的Maven模型。这项工作由Maven
Model Builder组件完成。
建立模型的过程非常复杂,许多步骤可能分为两个阶段,但是我们在模型插值部分对此感兴趣。这是Maven在模型
${...}中用计算值替换所有标记所用的时间。它在注入配置文件并执行继承之后发生。在那个时候,以MavenProject对象表示的Maven项目还不存在,只有它
Model正在构建中。只有拥有完整的模型之后,您才能开始从中构建Maven项目。
这样,完成插值时,仅根据POM文件中存在的信息进行解释,唯一有效的值是模型参考中提到的值。(
StringSearchModelInterpolator如果要查看源代码,则由类执行此替换。)值得注意的是,您会注意到
<parent>模型中的元素
不 包含父模型的名称。类
ModelMaven中实际上是与生成MODELLO从源
.mdo文件,和其源仅定义
groupId,
artifactId,
version和
relativePath(连同定制
id)的
<parent>元件。这在文档中也可见。
所有这些的结果是,在执行模型插值后,
${project.parent.name}将不会替换令牌。而且,MavenProject从中构造的名称将包含未
${project.parent.name}替换的名称。您可以在日志中看到此示例项目中的[INFO] Reactor Build Order:[INFO] [INFO] company-any-artifact[INFO] ${project.parent.name}-any-module[INFO] ${project.parent.name}-any-submodule这意味着Maven的考虑项目的实际名称
any-module是
${project.parent.name}-any-module。第2部分:怪异开始
现在,我们已经正确地创建甚至编译了反应堆中的所有项目。实际上,理论上所有内容都可以正常工作,但项目本身的名称完全令人讨厌。但是,您遇到了一个奇怪的情况,在使用创建JAR时,它失败了
maven-jar-plugin。在您的示例中,构建失败并显示以下日志:
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ any-submodule ---[INFO] ------------------------------------------------------------------------[INFO] Reactor Summary:[INFO] [INFO] company-any-artifact ............................... SUCCESS [ 0.171 s][INFO] ${project.parent.name}-any-module .................. SUCCESS [ 0.002 s][INFO] ${project.parent.name}-any-submodule ............... FAILURE [ 0.987 s][INFO] ------------------------------------------------------------------------[INFO] BUILD FAILURE[INFO] ------------------------------------------------------------------------表示在建立模型后出现了一些问题。原因是该插件将项目名称作为参数注入:
/** * Name of the generated JAR. * * @parameter alias="jarName" expression="${jar.finalName}" **default-value=”${project.build.finalName}”*
* @required
/
private String finalName;
注意
project.build.finalName,将其作为子模块生成的JAR名称的默认值。注入和变量的插值由另一个称为的类完成
PluginParameterexpressionevaluator。
那么这会发生什么:
- 上的JAR插件
any-submodule
注入了项目的最终名称,名为${project.parent.name}-any-submodule。 - 感谢您从父项目继承,并在
<finalName>
最顶层的POM项目中声明,它继承了<finalName>${project.name}-${project.version}</finalName>。 - Maven的现在尝试插值
${project.name}的any-submodule
。 ${project.parent.name}-any-submodule由于第1部分,因此解决为。- Maven的现在尝试插值
${project.parent.name}的any-submodule
。这可以正常工作:MavenProject
已构建并将getParent()
在项目实例上调用,返回具体的Maven父项目。因此,${project.parent.name}将尝试解析的名称any-module
,实际上是${project.parent.name}-any-module。 - Maven现在尝试进行插值
${project.parent.name}-any-module, 但仍在any-submodule
项目实例上。对于PluginParameterexpressionevaluator
,"project"
评估令牌的根没有改变。 - Maven现在尝试在
${project.parent.name}上进行插值any-submodule
,该插值再次可以正常工作并返回${project.parent.name}-any-module。 - Maven现在尝试
${project.parent.name}在any-submodule
…上进行插值,该方法可以工作并返回,${project.parent.name}-any-module因此它尝试评估${project.parent.name}…
您会看到这里发生了无尽的递归,从而导致了
StackOverflowError您的拥有。这是错误
PluginParameterexpressionevaluator吗?尚不清楚:这是因为最初没有正确替换的模型值。从理论上讲,它可以处理评估的特殊情况
${project.parent}并PluginParameterexpressionevaluator在此父项目上创建新工作,而不是始终在当前项目上工作。如果对此有强烈的想法,请随时创建JIRA问题。
第3部分:为什么没有子模块也能工作
通过上面所说的,您现在可以推断出在这种情况下它为什么起作用了。让我们来解释一下Maven需要做什么来评估最终名称,就像必须注入Maven Jar插件中一样:
- 上的JAR插件
any-module
注入了项目的最终名称,名为${project.parent.name}-any-module。 - 感谢您从父项目继承,并在
<finalName>
最顶层的POM项目中声明,它继承了<finalName>${project.name}-${project.version}</finalName>。 - Maven的现在尝试插值
${project.name}的any-module
。 - 解析为
${project.parent.name}-any-module,和以前一样。 - Maven的现在尝试插值
${project.parent.name}的any-module
。像以前一样,它可以正常工作:生成了MavenProject
,getParent()
并将在项目实例上调用,返回具体的Maven父项目。因此,${project.parent.name}将尝试解析的名称any-artifact
,实际上是company-any-artifact
。 - 插值成功并且停止。
而且您没有任何错误。



