我熟悉 Maven 项目(例如
my-app
)如何强制传递依赖项的版本。今天我偶然发现了一个相关问题:库my-lib
如何强制其与my-app
相关的传递依赖项的版本而不直接包含传递依赖项?
我有一个库
my-lib
,其唯一目的是让其他项目可以轻松地同时包含多个传递依赖项 - 换句话说,my-lib
有点像捆绑机制。在 my-lib/pom.xml
我正式声明 com.amazonaws:aws-lambda-java-log4j2:1.5.1
然后使用它:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-log4j2</artifactId>
<version>1.5.1</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-log4j2</artifactId>
</dependency>
</dependencies>
但是我想覆盖正在使用的 Log4j 版本,因此在
my-lib-parent
中我导入了特定的 Log4j BOM 版本:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-bom</artifactId>
<version>2.20.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
<dependencyManagement>
果然,如果我在
mvn dependency:tree
上做一个my-lib
,就表明正在使用Log4j 2.20.0:
[INFO] +- com.amazonaws:aws-lambda-java-log4j2:jar:1.5.1:compile
[INFO] | +- org.apache.logging.log4j:log4j-core:jar:2.20.0:compile
[INFO] | \- org.apache.logging.log4j:log4j-api:jar:2.20.0:compile
所以我很高兴地将
my-lib
添加为 my-app
的依赖项。 (请注意,我用 my-lib
指定 <scope>provided</scope>
;我不知道这是否对这个特定问题有影响。我已配置我的 Maven 程序集描述符以创建一个 ZIP 文件,即使使用带有 <scope>provided</scope>
的库也是如此。 )当我的代码尝试记录信息时,我得到了 java.lang.NoClassDefFoundError: org/apache/logging/log4j/BridgeAware
。事实证明,即使 my-lib
项目正在使用 org.apache.logging.log4j:log4j-core:jar:2.20.0
,但这也仅与 my-lib
本身相关——就 my-lib
而言,它不会影响
my-app
引入的传递依赖项的版本,当
my-app
包含 my-lib
作为依赖项时!
因此,如果我在
mvn dependency:tree
上执行 my-app
,则表明正在使用 org.apache.logging.log4j:log4j-api:jar:2.17.1
:
[INFO] | +- com.amazonaws:aws-lambda-java-log4j2:jar:1.5.1:provided
[INFO] | | +- org.apache.logging.log4j:log4j-core:jar:2.17.1:provided
[INFO] | | \- org.apache.logging.log4j:log4j-api:jar:2.17.1:provided
我想这是有道理的,但坦白说我从来没有想过太多。我刚刚假设
my-app
将获得由 my-lib
中的依赖管理设置的传递依赖项的版本。
我注意到
org.apache.logging.log4j:log4j-slf4j2-impl:jar:2.20.0
在 my-app
中获得了正确的版本,它也通过 Log4j BOM 进入 my-lib
,但这似乎是因为 my-lib
明确包含 org.apache.logging.log4j:log4j-slf4j2-impl:jar:2.20.0
作为其直接依赖项。
这就是唯一的解决方案:如果我希望当
com.amazonaws:aws-lambda-java-log4j2
包含在另一个版本中时将它们设置为另一个版本,我是否被迫去查找并枚举 my-lib
的所有传递依赖项并在 my-lib
中显式声明它们项目?是否有一种更简单的方法,类似于导入 BOM,允许 my-lib
简单地说“当 my-lib
包含在另一个项目中时,强制所有传递 Log4j 版本为 Log4j BOM 的版本”?
我过去也偶然发现了这个问题:DependencyManagement 是不可传递的。
您可以通过使用扁平Maven插件来生成“消费者pom”来避免该问题。