Maven 的依赖管理是项目构建的核心,通过 pom.xml 中的 dependencies 元素声明项目所需的第三方库。以下是对依赖使用的系统性总结,涵盖常见场景和最佳实践。
1. 基本依赖声明
xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.7.0</version>
<scope>compile</scope> <!-- 默认 compile -->
<optional>false</optional> <!-- 默认 false -->
<exclusions>
<exclusion>
<groupId>...</groupId>
<artifactId>...</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
必填项:groupId、artifactId、version(除非继承父POM或由 dependencyManagement 管理,version可以不填)。
2. 依赖范围(Scope)
| Scope | 编译器 | 测试期 | 运行期 | 打包包含 | 典型场景 |
|---|---|---|---|---|---|
| compile | ✔ | ✔ | ✔ | ✔ | 核心库 |
| provided | ✔ | ✔ | ✘ | ✘ | lombok等 |
| runtime | ✘ | ✔ | ✔ | ✔ | jdbc驱动 |
| test | ✘ | ✔ | ✘ | ✘ | JUnit、Mockito |
| system | ✔ | ✔ | ✘ | ✘ | 本地JAR(需配合,不推荐) |
| import | - | - | - | - | 仅用于 dependencyManagement,导入BOM |
import 的关键约束:
xml
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.7.0</version>
<type>pom</type> <!-- 必须指定 type=pom -->
<scope>import</scope> <!-- 必须指定 scope=import -->
</dependency>
</dependencies>
</dependencyManagement>
- 只能用在 dependencyManagement 中,不能出现在普通的 dependencies 里。
- 必须指定 pom,因为导入的目标是一个 POM 文件,而不是 jar。
- 必须指定 import,告诉 Maven 这是导入依赖管理,而不是实际引入依赖。
- 被导入的 POM 必须本身包含 节,否则导入无效。
3. 排除依赖项(Exclusions)
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.7.0</version>
<scope>compile</scope> <!-- 默认 compile -->
<optional>false</optional> <!-- 默认 false -->
<exclusions>
<exclusion>
<groupId>...</groupId>
<artifactId>...</artifactId>
</exclusion>
</exclusions>
</dependency>
典型场景:排除旧版commons-logging、 Log4j、SLF4J 桥接冲突,gson等。
4. 依赖不传递(Optional )
它的核心作用是控制依赖的传递性:当一个依赖被声明为 optional=true 时,该依赖不会自动传递给依赖当前项目的下游项目。
xml
<dependency>
<groupId>com.example</groupId>
<artifactId>some-lib</artifactId>
<version>1.0</version>
<optional>true</optional> <!-- 默认 false -->
</dependency>
- optional 默认为 false,表示该依赖是必需的,并且会向下游传递。
- 设置为 true 后,该依赖不会被下游项目继承,但当前项目本身仍然可以使用它(编译、测试、运行都需要它)。
5. 引用本地jar(system)
xml
<dependency>
<groupId>com.legacy</groupId>
<artifactId>old-lib</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/old-lib.jar</systemPath>
</dependency>
强烈不建议使用本地依赖,推荐上传到maven私服,主要有下述几个原因:
- 该 jar 不会被打入 WAR/JAR 包(除非额外配置 maven-war-plugin)
- 无法被传递依赖引用
- 跨机器构建时路径可能不一致
- 无法被依赖分析工具识别
6. 依赖检查两个常用命令
bash
mvn dependency:tree # 查看完整依赖树
mvn dependency:analyze # 分析未使用/未声明的依赖
- 定期清理无用依赖:运行 mvn dependency:analyze 找出 Unused declared dependencies 和 Used undeclared dependencies。