1. 什么是 Dependency Convergence?
Dependency Convergence 是指在 Maven 项目中,所有传递性依赖项(transitive dependencies)的版本号保持一致。如果多个依赖项引入了同一个库的不同版本,可能会导致冲突或不一致的行为。Dependency Convergence 的目标是确保项目中使用的每个库只有一个明确的版本。
2. 为什么需要 Dependency Convergence?
- 避免冲突:不同版本的库可能包含不兼容的 API 或行为,导致运行时错误。
- 简化管理:统一的版本号便于维护和升级。
- 提高稳定性:确保所有模块使用相同的依赖版本,减少意外行为。
3. 如何实现 Dependency Convergence?
(1) 使用 <dependencyManagement>
在 pom.xml
中使用 <dependencyManagement>
标签统一管理依赖版本。例如:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
</dependencies>
</dependencyManagement>
(2) 使用 BOM(Bill of Materials)
BOM 是一种特殊的 POM 文件,用于定义一组依赖项及其版本。通过引入 BOM,可以确保项目中使用的依赖版本一致。例如:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.7.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
(3) 使用 mvn dependency:tree
检查依赖
运行以下命令查看项目的依赖树,检查是否存在版本冲突:
mvn dependency:tree
(4) 使用 mvn enforcer:enforce
强制依赖收敛
Maven Enforcer 插件可以强制检查依赖收敛。在 pom.xml
中配置:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>enforce</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<DependencyConvergence/>
</rules>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
如果存在版本冲突,Maven 会报错并提示需要解决的依赖。
4. 解决依赖冲突
(1) 排除传递性依赖
使用 <exclusions>
标签排除不需要的传递性依赖。例如:
<dependency>
<groupId>org.example</groupId>
<artifactId>project-a</artifactId>
<version>1.0.0</version>
<exclusions>
<exclusion>
<groupId>org.example</groupId>
<artifactId>project-b</artifactId>
</exclusion>
</exclusions>
</dependency>
(2) 显式声明依赖版本
在 <dependencies>
中显式声明依赖版本,覆盖传递性依赖的版本。例如:
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
</dependencies>
(3) 使用 <dependencyManagement>
统一版本
在 <dependencyManagement>
中定义依赖版本,确保所有模块使用相同的版本。例如:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
</dependencies>
</dependencyManagement>
5. 示例:依赖收敛的 pom.xml
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>my-project</artifactId>
<version>1.0.0</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.example</groupId>
<artifactId>project-a</artifactId>
<version>1.0.0</version>
<exclusions>
<exclusion>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>enforce</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<DependencyConvergence/>
</rules>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
6. 总结
Dependency Convergence 是 Maven 项目中确保依赖版本一致性的重要机制。通过使用 <dependencyManagement>
、BOM 和 Maven Enforcer 插件,可以有效解决依赖冲突,提高项目的稳定性和可维护性。
更多详细信息,请参考 Maven 官方文档:https://maven.apache.org/enforcer/enforcer-rules/dependencyConvergence.html。
Legend: [Error] At least one dependency has a differing version of the dependency or has SNAPSHOT dependencies.
Statistics: Number of dependencies (NOD): 39
Number of unique artifacts (NOA): 49
Number of version-conflicting artifacts (NOC): 4
Number of SNAPSHOT artifacts (NOS): 0
Convergence (NOD/NOA): [Error] 79 %
Ready for release (100% convergence and no SNAPSHOTS): [Error] Error
You do not have 100% convergence.
Dependencies used in this project
org.apache.maven.shared:maven-shared-utils
[Error]
3.0.0
org.apache.maven.plugins:maven-ejb-plugin:maven-plugin:3.0.1
\- org.apache.maven.shared:maven-filtering:jar:3.1.1:compile
\- (org.apache.maven.shared:maven-shared-utils:jar:3.0.0:compile - omitted for conflict with 3.2.0)
3.2.0
org.apache.maven.plugins:maven-ejb-plugin:maven-plugin:3.0.1
\- org.apache.maven:maven-archiver:jar:3.2.0:compile
\- org.apache.maven.shared:maven-shared-utils:jar:3.2.0:compile
org.codehaus.plexus:plexus-archiver
[Error]
2.2
org.apache.maven.plugins:maven-ejb-plugin:maven-plugin:3.0.1
\- org.apache.maven.plugin-testing:maven-plugin-testing-harness:jar:2.1:test
\- (org.codehaus.plexus:plexus-archiver:jar:2.2:test - omitted for conflict with 3.5)
3.5
org.apache.maven.plugins:maven-ejb-plugin:maven-plugin:3.0.1
+- org.apache.maven:maven-archiver:jar:3.2.0:compile
| \- (org.codehaus.plexus:plexus-archiver:jar:3.5:compile - omitted for duplicate)
\- org.codehaus.plexus:plexus-archiver:jar:3.5:compile
org.codehaus.plexus:plexus-interpolation
[Error]
1.14
org.apache.maven.plugins:maven-ejb-plugin:maven-plugin:3.0.1
+- org.apache.maven:maven-core:jar:3.0:compile
| +- org.apache.maven:maven-settings-builder:jar:3.0:compile
| | \- (org.codehaus.plexus:plexus-interpolation:jar:1.14:compile - omitted for duplicate)
| +- org.apache.maven:maven-model-builder:jar:3.0:compile
| | \- (org.codehaus.plexus:plexus-interpolation:jar:1.14:compile - omitted for duplicate)
| \- (org.codehaus.plexus:plexus-interpolation:jar:1.14:compile - omitted for conflict with 1.24)
\- org.apache.maven:maven-compat:jar:3.0:test
\- (org.codehaus.plexus:plexus-interpolation:jar:1.14:test - omitted for conflict with 1.24)
1.22
org.apache.maven.plugins:maven-ejb-plugin:maven-plugin:3.0.1
+- org.apache.maven:maven-archiver:jar:3.2.0:compile
| \- (org.codehaus.plexus:plexus-interpolation:jar:1.22:compile - omitted for conflict with 1.14)
\- org.apache.maven.shared:maven-filtering:jar:3.1.1:compile
\- (org.codehaus.plexus:plexus-interpolation:jar:1.22:compile - omitted for conflict with 1.14)
1.24
org.apache.maven.plugins:maven-ejb-plugin:maven-plugin:3.0.1
\- org.codehaus.plexus:plexus-interpolation:jar:1.24:compile
org.codehaus.plexus:plexus-utils
[Error]
1.4.2
org.apache.maven.plugins:maven-ejb-plugin:maven-plugin:3.0.1
\- org.apache.maven:maven-compat:jar:3.0:test
\- org.apache.maven.wagon:wagon-provider-api:jar:1.0-beta-6:test
\- (org.codehaus.plexus:plexus-utils:jar:1.4.2:test - omitted for conflict with 3.1.0)
1.5.5
org.apache.maven.plugins:maven-ejb-plugin:maven-plugin:3.0.1
\- org.apache.maven:maven-core:jar:3.0:compile
\- org.sonatype.plexus:plexus-sec-dispatcher:jar:1.3:compile
\- (org.codehaus.plexus:plexus-utils:jar:1.5.5:compile - omitted for conflict with 2.0.4)
1.5.8
org.apache.maven.plugins:maven-ejb-plugin:maven-plugin:3.0.1
\- org.apache.maven.shared:maven-filtering:jar:3.1.1:compile
\- org.sonatype.plexus:plexus-build-api:jar:0.0.7:compile
\- (org.codehaus.plexus:plexus-utils:jar:1.5.8:compile - omitted for conflict with 2.0.4)
2.0.4
org.apache.maven.plugins:maven-ejb-plugin:maven-plugin:3.0.1
+- org.apache.maven:maven-plugin-api:jar:3.0:compile
| \- org.apache.maven:maven-model:jar:3.0:compile
| \- (org.codehaus.plexus:plexus-utils:jar:2.0.4:compile - omitted for duplicate)
+- org.apache.maven:maven-core:jar:3.0:compile
| +- org.apache.maven:maven-settings:jar:3.0:compile
| | \- (org.codehaus.plexus:plexus-utils:jar:2.0.4:compile - omitted for duplicate)
| +- org.apache.maven:maven-settings-builder:jar:3.0:compile
| | \- (org.codehaus.plexus:plexus-utils:jar:2.0.4:compile - omitted for duplicate)
| +- org.apache.maven:maven-repository-metadata:jar:3.0:compile
| | \- (org.codehaus.plexus:plexus-utils:jar:2.0.4:compile - omitted for duplicate)
| +- org.apache.maven:maven-model-builder:jar:3.0:compile
| | \- (org.codehaus.plexus:plexus-utils:jar:2.0.4:compile - omitted for duplicate)
| \- (org.codehaus.plexus:plexus-utils:jar:2.0.4:compile - omitted for conflict with 3.1.0)
+- org.apache.maven:maven-artifact:jar:3.0:compile
| \- (org.codehaus.plexus:plexus-utils:jar:2.0.4:compile - omitted for duplicate)
\- org.apache.maven:maven-compat:jar:3.0:test
\- (org.codehaus.plexus:plexus-utils:jar:2.0.4:test - omitted for conflict with 3.1.0)
2.0.5
org.apache.maven.plugins:maven-ejb-plugin:maven-plugin:3.0.1
\- org.apache.maven:maven-plugin-api:jar:3.0:compile
\- org.sonatype.sisu:sisu-inject-plexus:jar:1.4.2:compile
\- (org.codehaus.plexus:plexus-utils:jar:2.0.5:compile - omitted for conflict with 2.0.4)
3.0.24
org.apache.maven.plugins:maven-ejb-plugin:maven-plugin:3.0.1
+- org.apache.maven:maven-archiver:jar:3.2.0:compile
| \- (org.codehaus.plexus:plexus-utils:jar:3.0.24:compile - omitted for conflict with 2.0.4)
+- org.apache.maven.shared:maven-filtering:jar:3.1.1:compile
| \- (org.codehaus.plexus:plexus-utils:jar:3.0.24:compile - omitted for conflict with 2.0.4)
\- org.codehaus.plexus:plexus-archiver:jar:3.5:compile
+- (org.codehaus.plexus:plexus-utils:jar:3.0.24:compile - omitted for conflict with 3.1.0)
\- org.codehaus.plexus:plexus-io:jar:3.0.0:compile
\- (org.codehaus.plexus:plexus-utils:jar:3.0.24:compile - omitted for conflict with 3.1.0)
3.1.0
org.apache.maven.plugins:maven-ejb-plugin:maven-plugin:3.0.1
\- org.codehaus.plexus:plexus-utils:jar:3.1.0:compile