导入两个含测试依赖的BOM时为何引入错误版本依赖?
一、Test Scope依赖被引入的原因
首先明确:BOM本身不引入任何依赖,它只负责锁定依赖版本。你看到的testcontainers依赖,是项目A的module1里直接声明的(test scope),而projecta-bom的dependencyManagement只是给这些依赖统一了版本。
当项目B导入projecta-bom时,会继承其中所有的dependencyManagement规则——不管这些规则对应的依赖是test scope还是compile scope。只要项目B(或其依赖的模块)有引入这些testcontainers依赖的需求(哪怕是test阶段用),Maven就会用projecta-bom里锁定的1.16.3版本。
说白了:不是BOM“带进来”了test scope依赖,是你的项目里本来就有这些依赖的声明,BOM只是帮它们定了版本,scope还是由原始的依赖声明说了算。
二、版本优先级的逻辑
你说的“先声明的BOM版本优先”完全正确,但这里的关键是:projecta-bom里已经包含了testcontainers相关依赖的版本规则(1.16.3)。当项目B先导入projecta-bom,再导入1.18.3的testcontainers-bom时,对于那些已经被projecta-bom锁定版本的testcontainers依赖,后导入的BOM无法覆盖——Maven会优先采用先声明的版本规则。
这就是为什么你看到的还是1.16.3版本。
三、你的操作与认知误区
操作上没有错,但对BOM和scope的关系有误解:
- 误区1:以为BOM会过滤不同scope的依赖,实际上BOM不管scope,只管理版本,scope由实际的
<dependency>声明决定。 - 误区2:以为后导入的高版本BOM能覆盖所有同artifact的版本,但如果先导入的BOM已经对该artifact做了版本锁定,就会优先生效。
四、解决方法
如果想让项目B用1.18.3的testcontainers版本,有两种可行方式:
- 调整BOM导入顺序:把1.18.3的testcontainers-bom放在projecta-bom前面导入。这样高版本的BOM规则会先锁定testcontainers的版本,覆盖projecta-bom里的旧版本。
<dependencyManagement> <!-- 先导入高版本BOM --> <dependency> <groupId>org.testcontainers</groupId> <artifactId>testcontainers-bom</artifactId> <version>1.18.3</version> <type>pom</type> <scope>import</scope> </dependency> <!-- 再导入projecta-bom --> <dependency> <groupId>你的项目组ID</groupId> <artifactId>projecta-bom</artifactId> <version>对应版本号</version> <type>pom</type> <scope>import</scope> </dependency> </dependencyManagement> - 显式声明版本:在项目B的dependencyManagement里,直接给testcontainers:jdbc和testcontainers:postgresql指定1.18.3版本,手动覆盖BOM的规则。
内容的提问来源于stack exchange,提问作者Wonger

