繁体   English   中英

Maven 依赖项以及它们在 Java 项目中的实际工作方式

[英]Maven dependencies and how they actually work in Java projects

我在谷歌上寻找这些答案,但找不到我的问题的确切答案,通常只是 Maven 以及 pom 和生命周期阶段的概述。 我的确切问题是:

  1. 传递依赖。 假设我有一个主要的 Java 项目,称为“Project-A”,它有另一个项目作为其依赖项,例如数据库 java 项目,该项目具有所有 CRUD 方法,称为“Dependency-X”,具有spring-boot-starter-jpa-1.XX版本在其 POM 中列出。 现在说我也在Java Project-A的POM中直接声明spring-boot-starter-jpa-2.XX (注意版本)。 如果我正确理解传递依赖项,spring-boot-starter-jpa-1.XX(来自 Dependency-X db 项目)将通过 Dependency-X (db) 项目传递(间接)导入。 那么哪个依赖会获胜? 哪个被进口? 由于它们是两个不同的版本,这显然是一个问题。 您是否必须在 POM 中的所有依赖项中显式添加<exclusion>标记,以拉入与您的项目当前依赖项冲突的其他传递依赖项?

IE 在此处输入图像描述

  1. 多重依赖 当您在 pom.xml 中声明依赖项时,当您包含相同的依赖项两次不同版本时会发生什么; 哪个被选中/导入到您的项目中,Maven 是如何决定的? 我假设,如果 maven 在你的<repositories>列表中列出的第一个 repo 中找不到这个依赖项-a(假设你列出了超过 1 个 repo)你的 pom,它将 go 在列表中 1-by- 1 直到它发现它是正确的? IE
<dependency>
            <groupId>org.mydependency</groupId>
            <artifactId>dependency-a</artifactId>
            <version>6.6.6</version>
</dependency>
<dependency>
            <groupId>org.mydependency</groupId>
            <artifactId>dependency-a</artifactId>
            <version>8.8.8</version>
</dependency>
  1. parent-pom 到底是如何工作的? 我知道我可以在其中包含带有依赖项的<parent></parent>标记,我可以单击 ctrl + B (windows)或 command + B (mac),它将带我到源 pom (父级),我可以查看所有内容。 这是如何工作的——它从哪里得到这个文件?

是否所有“父”pom,例如“spring-boot-starter-jpa”依赖项实际上只是指向 maven 中央存储库上的 POM 文件,进一步指向单个 JARS,Z402C5D9AF6B437174DZ 解析并导入到您的项目中?

IE

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.4.4</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>

  <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
            <version>${spring.boot.version}</version>
</dependency>

就解决传递依赖而言,最短路径获胜。 这也记录在这里

Dependency mediation - this determines what version of an artifact will be chosen when multiple versions are encountered as dependencies. Maven picks the "nearest definition". That is, it uses the version of the closest dependency to your project in the tree of dependencies. You can always guarantee a version by declaring it explicitly in your project's POM. Note that if two dependency versions are at the same depth in the dependency tree, the first declaration wins.
"nearest definition" means that the version used will be the closest one to your project in the tree of dependencies. Consider this tree of dependencies:
  A
  ├── B
  │   └── C
  │       └── D 2.0
  └── E
      └── D 1.0
In text, dependencies for A, B, and C are defined as A -> B -> C -> D 2.0 and A -> E -> D 1.0, then D 1.0 will be used when building A because the path from A to D through E is shorter.

那么哪个依赖获胜? 哪个被进口?

引导启动器 jpa 2.x 获胜,因为它具有最短路径。

对于同一依赖项的多个版本,我建议运行

mvn dependency:tree

查看包含哪一个或是否有错误。

parent-pom 到底是如何工作的?

父 pom 只是对当前项目“继承”的项目的引用。 关于如何从父母那里解决依赖关系有一定的规则。 在我看来,最重要的事情是,父级允许您在所有兄弟项目都可以从中继承其依赖项的地方为常见的兄弟项目添加依赖项。 Spring boot 就按照这个模式来引入starter pom版本解析。 当然,拥有父 pom 是可选的,您可以拥有一个没有父 pom 的项目。

  1. 通常,如果您在依赖关系树中有相同 jar 的不同版本,则“最近”依赖关系获胜。

  2. 您可以通过在<dependencyManagement>中显式设置传递依赖项的版本来覆盖此行为。 不要使用排除项来管理版本。

  3. 父对象像依赖项一样被解析,即来自像 MavenCentral 这样的存储库。

  4. 父项和您的 POM 的内容被“合并”,导致您可以在命令行或 IDE 中查看的“有效 POM”。

parent-pom 到底是如何工作的?

您似乎想了解 inheritance 项目在 Maven 中的工作原理。 这是一个广阔的主题。 这解决了构建 pom(项目继承)的主要方法以及与.

关于你的前两个问题:

那么哪个依赖会获胜? 哪个被进口?

当您包含相同的依赖项两次不同的版本时会发生什么; 哪个被选中/导入到您的项目中,Maven 是如何决定的?

虽然您的问题是有道理的,但 Maven 随着时间的推移并没有提供任何具体的保证。 版本冲突的结果只是一个实现细节。
我更愿意告诉你,为了根据你的依赖版本的要求保证一致的打包,你必须对此进行明确的检查。
您可以实现它或仅使用 maven 插件,例如maven-enforcer-plugin现有规则,例如:

  • dependencyConvergence - 确保所有依赖项收敛到相同的版本。
  • banDuplicatePomDependencyVersions - 强制项目没有重复声明的依赖项。
  • requireUpperBoundDeps - 确保每个(传递)依赖项都解析为其指定的版本或更高版本。

规则列表非常密集,如果没有人符合您的需求,您甚至可以编写自己的规则。

如何使用dependencyConvergence 规则声明插件执行的示例:

<project>
  ...
  <build>
    <plugins>
      ...
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-enforcer-plugin</artifactId>
        <version>3.0.0-M3</version>
        <executions>
          <execution>
            <id>enforce</id>
            <configuration>
              <rules>
                <dependencyConvergence/>
              </rules>
            </configuration>
            <goals>
              <goal>enforce</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      ...
    </plugins>
  </build>
  ...
</project>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM