maven 如何解决 spring data gemfire 的 slf4j 依赖关系?

How's maven resolving the slf4j dependency of spring data gemfire?

Spring data gemfire 1.7.0.RELEASEslf4j-apijcl-over-slf4j 的版本 1.7.12 具有编译时依赖性。我在我的 maven pom 文件中定义了以下依赖项,因为我们需要 slf4j 1.7.10 依赖项(很少有其他 jar 依赖于此):

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-gemfire</artifactId>
    <version>1.7.0.RELEASE</version>
</dependency>   

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.10</version>
</dependency>

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jcl-over-slf4j</artifactId>
    <version>1.7.10</version>
    <scope>runtime</scope>
</dependency>

我有一个内部 Maven 仓库作为 Maven 中央仓库。以下是我在不同场景中看到的行为,基于 Maven 中心可用的 jar:

我的问题:

  1. 在场景 1 中,我不明白为什么构建没有抱怨缺少 1.7.12 jar。依赖是如何解决的?
  2. 在场景 2 中,如果我没有在 spring 数据依赖项中指定对 slf4j 1.7.12 的排除,1.7.10 jar 如何覆盖 1.7.12?
  3. 在场景3中,当Maven Central 中缺少slf4j-parent 1.7.12 的pom 时,为什么会报错?由于存在 1.7.10 罐子,构建 运行 是否应该可以很好地拾取 1.7.10 罐子(类似于场景 1)?

答案基于Maven Dependencies Mediation机制,具体是这样的说法:

You can always guarantee a version by declaring it explicitly in your project's POM

因此,从本质上讲,通过将其显式声明为依赖项的一部分,您将覆盖传递依赖项的任何版本,因此您不需要添加任何排除项。你声明它,你有项目的知识,Maven信任你。

因此,在场景 1 和 2 中,Maven 应用了上述规则,并仅遵循 POM 中指定的内容。
在场景 1 中,由于它根本没有找到任何 1.7.12 版本,它甚至没有尝试解析它并信任你的 POM。
在场景 2 中,它解析了 1.7.12 的依赖项树,但随后根据您的 POM,版本 1.7.10 获胜。
在场景 3 中,它无法解析版本 1.7.12 的整个依赖树,因此它给出了一个错误:是的,你的 POM 中的版本无论如何都会赢,但是因为 Maven在获取完整的依赖关系树时出错,然后执行失败。

这是一个特例,最终确认只能看你使用的Maven版本的相关代码。

更新
我建议在三种情况下尝试获得更多细节,是从控制台 运行:

mvn dependency:resolve -Dsort=true -X

由于调试标志,它将在依赖调解过程中提供包含和排除的依赖项列表。

作为补充,运行宁:

mvn dependency:tree

将为您提供完整的依赖关系图,显示实际从 POM 中获取的内容以及通过传递依赖项获得的内容。这可能会给你更多的信息。有关详细信息,我建议查看 Maven Dependency Plugin 目标。