Maven:学习笔记

Maven 是一个跨平台的项目管理工具,主要服务于基于 Java 平台的项目构建、依赖管理和项目信息管理。

坐标

Maven 定义了这样这样一组规则:世界上任何一个构件都可以用 Maven 坐标唯一标识,Maven 坐标元素包括:

  • groupId
  • artifactId
  • version
  • packaging
  • classifier

我们自己开发的项目也要为其定义适当的坐标,这是 Maven 强制要求的,在这个基础上,其他 Maven 项目可以应用此项目生成的构件。

依赖

当我们的项目要用依赖别的构件时,需要添加依赖申明,一个依赖申明包含如下元素:

  • groupId artifactId version 依赖的基本坐标
  • type 依赖的类型,对应项目坐标定义的 packaging,一般不必申明,缺省值 jar
  • scope 依赖范围
  • optional 标记依赖是否可选
  • exclusions 用来排除传递性依赖

Maven 项目生命周期中有三套 classpath (classpath 是指 JVM 的一个环境变量,用来指示 JVM 如何搜索 class), 分别是 编译 测试 运行。而上面的 scope 则指定了当前构件的依赖范围,scope 值有如下几个:

  • compile 对编译 测试 运行三个 classpath 均有效,如果没有指定,就会使用此值
  • test 仅对测试有效
  • provided 对编译和测试有效,运行时无效
  • runtime 对测试运行有效,编译时无效
  • system 对编译和测试有效,运行时无效,需通过 systemPath 元素显式指定依赖文件路径
  • import 不会对三种 classpath 产生实际影响

依赖传递

假设 A 依赖与于 B,B 依赖于 C,我们说 A 对于 B 是第一直接依赖,B 对于 C 是第二直接依赖,A 对于 C 是传递性依赖。第一依赖范围和第二依赖范围决定了依赖传递的范围。

下表 左边第一行表示第一直接依赖范围,最上面一行表示第二直接依赖范围。

依赖传递可以参考上图。

依赖调解

项目 A 有这样的依赖关系:A - B - C - X(1.0)  A - D - X(2.0),其中 X 是 A 的传递性依赖,但是两条依赖路径上有两个版本的 X,那么哪个版本的 X 会被 A 依赖呢?Maven依赖调解 dependency mdeiation 的第一原则是:路径最近者优先。因此上例中 X(2.0)会被依赖。依赖调解的第二原则:路径相同时,第一声明者优先。

生命周期

Maven 的生命周期就是为了对所有的构建过程进行抽象和统一。Maven 从大量项目和构建工具中进行学习和反思,总结了一套高度完善易于扩展的生命周期。Maven 生命周期是抽象的,这意味着生命周期本身不做任何实际的工作。在 Maven 的设计中,实际工作都交由插件来完成。

Maven 有三套相互独立的生命周期,分别是:

  • clean 清理项目
  • default 构建项目
  • site 建立项目站点

每个生命周期包含一些阶段 phase,这些阶段是有顺序的,并且后面的阶段依赖前面的阶段。用户和 Maven 最直接的交互方式就是条用这些生命周期的阶段。较之于阶段的前后依赖关系,三套生命周期之间是相互独立的。详细可以参考官方文档中的内容。

插件

Maven 生命周期与插件相互绑定,用以完成实际的构建任务。具体而言,是生命周期的阶段与插件目标 plugin goal 相互绑定,以完成某个具体的构建任务。插件目标 plugin goal 是指用户通过命令行输入的指令,可以调用插件中的某个功能。例如 compiler:compile 是调用插件 maven-compiler-plugin 的 compile 目标。

例如这个命令 mvn dependency:tree

上面命令的完整写法是 mvn org.apache.maven.plugins:maven-dependency-plugin:2.1:tree 这样插件的 groupId artifactId version goal 都被清晰的描述了。之所以有简单的写法,是因为 Maven 引入了前缀的概念,dependency 是 maven-dependency-plugin 的前缀,也就是插件的简易别名。有了插件前缀,Maven 就能找到对应的 artifactId。

插件设置前缀的规则如下:

  • maven-${prefix}-plugin 官方插件
  • ${prefix}-maven-plugin 第三方插件

为了让用户不做任何配置就能构建项目,Maven 为一些主要的生命周期阶段绑定了很多插件目标。 完成了插件和生命周期的绑定之后,用户还可以配置插件目标的参数,用户可以通过命令行或 POM 配置等方式来配置这些参数。在命令行中,用户可以使用 -D 参数,并伴随着一个参数键 = 参数值的形式,来配置插件目标的参数。

聚合和继承

一个常见的需求,我们会想要一次构建两个项目,而不是到两个模块目录下分别执行 mvn 命令。Maven 聚合这一特性就是就是为该需求服务的。对聚合模块来说,其打包方式 packaging 必须为 pom。为了方便用户构建项目,通常将聚合模块放在项目目录的最顶层,其他模块则作为聚合模块的子目录存在。

POM 有一种父子结构,在父 POM 中声明一些配置供子 POM 使用,以实现一处声明,处处使用的目的,这就是 Maven 中的继承关系。

Maven 提供的 dependencyManagement 元素下声明的依赖不会引入实际的依赖,但是只要子模块配置了 groupId artifactId 就能获得对应的依赖信息,从而引入正确的依赖。当依赖在父 POM 中声明版本后,子模块使用依赖时无须声明版本。

在现有的实际项目中,往往会发现一个 POM 既是聚合 POM,又是父 POM。

聚合和继承的区别:聚合是为了方便快速构建项目,继承是为了消除重复配置 

参考:

1 Maven实战 一书

2 生命周期和阶段 https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html#Lifecycle_Reference

3 插件前缀 http://maven.apache.org/guides/introduction/introduction-to-plugin-prefix-mapping.html

原文地址:https://www.cnblogs.com/colin220/p/12845480.html