MVN3️⃣依赖管理 & 生命周期及插件
1、依赖管理
依赖:当前项目运行所需要的 jar 包。
- 一个项目可以导入多个依赖,项目本身也可作为依赖被导入。
- 示例:项目 A 可通过项目 B 的 GAV 坐标将其导入,而不必将两个项目写在一起。
1.1、配置
-
配置方式:dependencies - dependency - gav。
<!-- 项目依赖 --> <dependencies> <!--具体依赖 --> <dependency> <!-- GAV 坐标 --> <groupId></groupId>> <artifactId></artifactId> <version></version> </dependency> </dependencies>
-
查看 Maven 依赖关系:Maven - Show Dependencies。
1.2、特点(❗)
1.2.1、传递
依赖具有传递性。
相对于当前项目,分为直接传递和间接传递。
-
直接传递:通过依赖配置建立的依赖关系(A 导入 B,则 AB 是直接传递)
-
间接传递:通过依赖配置间接建立的依赖关系(A 导入 B、B 导入 C,则 AC 是间接传递)
依赖中出现相同资源时,存在冲突问题。
冲突解决策略:按以下顺序处理
-
路径优先:资源相同,优先使用层级浅的。
-
声明优先:层级相同,优先使用先声明的。
-
特殊情况:一个项目中直接导入了相同资源的不同版本,使用后声明的。
(示例:项目中同时导入 JUnit 的两个版本,优先使用 4.12)
<dependencies> <!-- 先声明 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.27</version> </dependency> <!-- 后声明👍 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> </dependencies>
1.2.2、可选(optional)
(不开放,不给用)
开启 optional,对外隐藏当前所依赖的资源。
示例:A 导入 B,B 导入 C。
-
根据传递性,C 会被导入 A。
-
若 B 导入 C 时开启了 optional,则 C 不会被导入 A。
<!-- B的pom.xml --> <dependency> <groupId>indi.jaywee</groupId> <artifactId>projectC</artifactId> <version>1.0</version> <!-- true 表示生效 --> <optional>true</optional> </dependency>
1.2.3、排除(exclude)
(不需要,不使用)
指定 GA,排除依赖的资源。
示例:A 导入 B,B 导入 C。
-
根据传递性,C 会被导入 A。
-
若 A 导入 B 时通过 exclude 配置了 C 的 GA,则 C 不会被导入 A。
<!-- A的pom.xml --> <dependency> <groupId>indi.jaywee</groupId> <artifactId>projectB</artifactId> <version>1.0</version> <exclusions> <exclusion> <!-- 指定 GA --> <groupId>indi.jaywee</groupId> <artifactId>projectC</artifactId> </exclusion> </exclusions> </dependency>
可选 vs 排除
叛逆的 optional | 嫌弃的 exclude | |
---|---|---|
谁来配置? | 被使用者 B | 使用者 A |
什么效果? | B 被导入时,C 不给 A 用 | B 被导入时,A 不想用 C |
A 知道 C 的存在? | ❌ | ✔ |
1.3、依赖范围
1.3.1、scope(❗)
scope:指定依赖(jar 包)的作用范围
-
作用范围:
- main 可用
- test 可用
- 参与打包
-
scope 取值:默认 compile。
main 可用 test 可用 参与打包 示例 compile ✔ ✔ ✔ log4j provided ✔ ✔ servlet-api runtime ✔ jdbc test ✔ junit
示例
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
1.3.2、依赖范围传递
发生依赖的间接传递时,不同的 scope 会导致不同的结果。
示例:A 导入 B,B 导入 C。
-
传递前提:当前项目导入依赖的 scope 必须支持打包,才会被间接传递。
(B 导入的 C 必须是 compile/runtime,才会被导入 A)
<!-- 项目B --> <dependency> <groupId>indi.jaywee</groupId> <artifactId>projectC</artifactId> <version>1.0</version> <!-- compile/runtime --> <scope>?</scope> </dependency>
-
确定最终作用域
-
优先取 A:A 导入 B 配置的 scope
-
何时取 B:A 的 scope 支持打包,且 B 的 scope 不支持打包(需同时成立)。
B - compile B - runtime(不支持打包) A - compile compile runtime(仅此取 B) A - provided provided provided A - runtime runtime runtime A - test test test
-
2、生命周期及插件
2.1、生命周期
生命周期:描述项目构建过程中经历的阶段,每个阶段对应插件功能。
- clean:清理工作
- default:核心工作
- site:生成站点文档
2.1.1、clean
执行 clean 命令时,依次执行以下插件。
- pre-clean
- clean:清理上次构建生成的文件。
- post-clean
2.1.2、default(❗)
Hint:执行某一插件时,会按顺序先执行前面所有插件。
插件 | 作用 | 备注 |
---|---|---|
validate | 校验项目正确,信息完备 | |
initialize | 初始化构建状态 | 如设置属性值 |
generate-sources | 生成编译阶段中的源码 | main\java |
process-sources | 处理源码 | 如过滤任意值 |
generate-resources | 生成资源文件 | main\resources |
process-resources | 复制并处理资源文件 | 到 target 目录 |
compile | 编译项目源码,生成字节码文件 | 到 target\classes 目录 |
process-classes | 处理编译生成的字节码文件 | 如优化字节码文件 |
generate-test-sources | 生成编译阶段中的测试源码 | test\java |
process-test-sources | 处理测试源码 | 如过滤任意值 |
generate-test-resources | 创建测试资源文件 | test\resources |
process-test-resources | 复制并处理测试资源文件 | 到 target 目录 |
test-compile | 编译测试源码,生成字节码文件 | 到 target\test-classes 目录 |
process-test-classes | 处理编译生成的字节码文件 | 如优化字节码文件 |
test | 使用合适的单元测试框架(如 JUnit),执行测试用例,生成测试报告 | 到 target\surefilereports |
prepare-package | 打包前的准备工作 | |
package | 将编译后的代码打包成可分发格式的文件 | 根据 POM 定义的打包方式,如 JAR,WAR,EAR |
pre-integration-test | 集成测试前的准备工作 | 如搭建环境 |
integration-test | 处理和部署项目到可以运行集成测试环境中 | |
post-integration-test | 集成测试后的工作 | 如清理环境 |
verify | 执行任意检查工作,验证项目包有效且达到质量标准 | |
install | 安装项目包到本地仓库 | 此后该项目可作为依赖,被其它本地项目导入 |
deploy | 将项目包部署(复制)到远程仓库 | 同上,可在远程仓库的使用者中共享 |
2.1.3、site
- pre-site
- site:生成项目的站点文档。
- post-site
- site-deploy:将站点文档部署到特定服务器上。
2.2、插件
2.2.1、说明
- 插件与生命周期的阶段绑定,在对应阶段执行对应的若干个插件功能。
- 执行构建命令时,若本地没有命令对应的插件,Maven 会自动下载。
- Maven 为每个阶段预设了插件功能(👉见 2.1),也可自定义插件功能。
2.2.2、自定义插件
示例:自定义 maven-source-plugin 插件。
指定以下功能:
-
当执行到
generate-test-resources
阶段时。 -
使用 maven-source-plugin 插件将项目源码打成 jar 包。
<build> <plugins> <plugin> <!-- 插件 GAV 坐标--> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> <version>2.2.1</version> <!-- 执行功能 --> <executions> <execution> <!-- 执行目标 --> <goals> <goal>jar</goal> </goals> <!-- 执行阶段 --> <phase>generate-test-resources</phase> </execution> </executions> </plugin> </plugins> </build>