9.5.3. 项目继承

有些情况你会想要一个项目从父POM中继承一些值。你可能正构建一个大型的系统,你不想一遍又一遍的重复同样的依赖元素。如果你的项目通过parent元素使用继承,你就可以避免这种重复。当一个项目声明一个parent的时候,它从父项目的POM中继承信息。它也可以覆盖父POM中的值,或者添加一些新的值。

所有的Maven POM从父POM中继承值。如果一个POM没有通过parent元素指定一个直接的父项目,那这个POM就会从超级POM继承值。Example 9.12, “项目继承”展示了a-parentparent元素,它继承了a-parent项目定义的POM

Example 9.12. 项目继承

<project>
  <parent>
    <groupId>com.training.killerapp</groupId>
    <artifactId>a-parent</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <artifactId>project-a</artifactId>
  ...
</project>

project-a中运行会mvn help:effective-pom显示一个POM,该POM合并了超级POMa-parent中定义的POM,以及project-a中定义的POMproject-a显式的和隐式的继承关系如Figure 9.4, “a-parent和project的项目继承关系”所示:

a-parent和project的项目继承关系

Figure 9.4. a-parent和project的项目继承关系


当一个项目指定一个父项目的时候,Maven在读取当前项目的POM之前,会使用这个父POM作为起始点。它继承所有东西,包括groupIdversion。你会注意到project-a没有指定groupIdversion,它们从a-parent继承而来。有了parent元素,一个POM就只需要定义一个artifactId。但这不是强制的,project-a可以有一个不同的groupIdversion,但如果不提供值,Maven就会使用在父POM中指定的值。如果你开始使用Maven来管理和构建大型的多模块项目,你就会常常创建许多共享一组通用的groupIdversion的项目。

当你继承一个POM,你可以选择直接使用继承的POM信息,或者选择覆盖它。以下是一个Maven POM从它父POM中继承的项目列表:

  • 定义符(groupIdartifactId中至少有一个必须被覆盖)

  • 依赖

  • 开发者和贡献者

  • 插件列表

  • 报告列表

  • 插件执行 (id匹配的执行会被合并)

  • 插件配置

当Maven继承依赖的时候,它会将父项目中定义的依赖添加到子项目中。你可以使用Maven的这一特征来指定一些在所有项目被广泛使用的依赖,让它们从顶层POM中继承。例如,如果你的系统全局使用Log4J日志框架,你可以在你的顶层POM中列出该依赖。任何从该项目继承POM信息的项目会自动拥有Log4J依赖。类似的,如果你能确定每个项目都在使用同样版本的一个Maven插件,你可以在顶层父POMpluginManagement元素中显式的列出该Maven插件的版本。

Maven假设父POM在本地仓库中可用,或者在当前项目的父目录(../pom.xml) 中可用。如果两个位置都不可用,默认行为还可以通过relativePath元素被覆盖。例如,一些组织更喜欢一个平坦的项目结构,父项目的pom.xml并不在子项目的父目录中。它可能在项目的兄弟目录中。如果你的子项目在目录./project-a中,父项目在名为./a-parent的目录中,你可以使用如下的配置来指定parent-aPOM的相对位置。

<project>
  <parent>
    <groupId>org.sonatype.mavenbook</groupId>
    <artifactId>a-parent</artifactId>
    <version>1.0-SNAPSHOT</version>
    <relativePath>../a-parent/pom.xml</relativePath>
  </parent>
  <artifactId>project-a</artifactId>
</project>