maven依赖机制及依赖管理

亦凉 2022-05-26 03:27 345阅读 0赞

maven依赖机制及依赖管理

依赖性传递:

依赖调解:

当项目中出现多个版本构件依赖的情形,依赖调解决定最终应该使用哪个版本。当然,你也可以在项目POM文件中显式指定使用哪个版本。从Maven 2.0.9开始,POM中依赖声明的顺序决定了哪个版本会被使用,也叫作”第一声明原则”。
“短路径优先”意味着项目依赖关系树中路径最短的版本会被使用。例如,假设A、B、C之间的依赖关系是A->B->C->D(2.0)和A->E->(D1.0),那么D(1.0)会被使用,因为A通过E到D的路径更短。但如果你想要强制使用D(2.0),那你也可以在A中显式声明对D(2.0)的依赖。

依赖管理:

在出现传递性依赖或者没有指定版本时,项目作者可以通过依赖管理直接指定模块版本。之前的章节说过,由于传递性依赖,尽管某个依赖没有被A直接指定,但也会被引入。相反的,A也可以将D加入元素中,并在D可能被引用时决定D的版本号。

依赖范围:

你可以指定只在当前编译范围内包含合适的依赖。 下面会介绍更多相关的细节。

排除依赖如果项目X依赖于项目Y,项目Y又依赖项目Z,项目X的所有者可以使用”exclusion”元素来显式排除项目Z。

可选依赖

如果项目Y依赖项目Z,项目Y的所有者可以使用”optional”元素来指定项目Z作为X的可选依赖。那么当项目X依赖项目Y时,X只依赖Y并不依赖Y的可选依赖Z。项目X的所有者也可以根据自己的意愿显式指定X对Z的依赖。(你可以把可选依赖理解为默认排除)。

所以maven的依赖原则大致有一下几个:

  • 依赖路径最短优先原则:一个项目Demo依赖了两个jar包,其中A-B-C-X(1.0) , A-D-X(2.0)。由于X(2.0)路径最短,所以项目使用的是X(2.0)。
  • pom文件中申明顺序优先:如果A-B-X(1.0) ,A-C-X(2.0) 这样的路径长度一样怎么办呢?这样的情况下,maven会根据pom文件声明的顺序加载,如果先声明了B,后声明了C,那就最后的依赖就会是X(1.0)。
  • 覆写优先:子pom内声明的优先于父pom中的依赖。

依赖管理解决什么问题

当同一个工程内有多个模块时,并且要求多个模块使用某个 jar 包的相同版本,为了方便统一版本号,升级版本号,需要提取出一个父亲模块来管理子模块共同依赖的 jar 包版本。
举个例子:有两个模块 projectA, projectB,它们的依赖分别如下所示:

projectA:

  1. <project>
  2. <dependencies>
  3. <dependency>
  4. <groupId>group-a</groupId>
  5. <artifactId>artifact-a</artifactId>
  6. <version>1.0</version>
  7. <exclusions>
  8. <exclusion>
  9. <groupId>group-c</groupId>
  10. <artifactId>excluded-artifact</artifactId>
  11. </exclusion>
  12. </exclusions>
  13. </dependency>
  14. <dependency>
  15. <groupId>group-a</groupId>
  16. <artifactId>artifact-b</artifactId>
  17. <version>1.0</version>
  18. <type>bar</type>
  19. <scope>runtime</scope>
  20. </dependency>
  21. </dependencies>
  22. </project>

projectB:

  1. <project>
  2. ...
  3. <dependencies>
  4. <dependency>
  5. <groupId>group-c</groupId>
  6. <artifactId>artifact-b</artifactId>
  7. <version>1.0</version>
  8. <type>war</type>
  9. <scope>runtime</scope>
  10. </dependency>
  11. <dependency>
  12. <groupId>group-a</groupId>
  13. <artifactId>artifact-b</artifactId>
  14. <version>1.0</version>
  15. <type>bar</type>
  16. <scope>runtime</scope>
  17. </dependency>
  18. </dependencies>
  19. </project>

projectA 和 projectB 共同依赖了 group-a/artifact-b/1.0,提取公共依赖,生成 parent, parent 依赖如下:

  1. <project>
  2. ...
  3. <dependencyManagement>
  4. <dependencies>
  5. <dependency>
  6. <groupId>group-a</groupId>
  7. <artifactId>artifact-b</artifactId>
  8. <version>1.0</version>
  9. <type>bar</type>
  10. <scope>runtime</scope>
  11. </dependency>
  12. </dependencies>
  13. </dependencyManagement>
  14. </project>

则 projectA 和 projectB 均不需要指定 group-a/artifact-b 的 version 信息,未来升级 version 信息时,只需要在 parent 内部指定。

projectA:

  1. <project>
  2. ...
  3. <dependencies>
  4. <dependency>
  5. <groupId>group-a</groupId>
  6. <artifactId>artifact-a</artifactId>
  7. <version>1.0</version>
  8. <exclusions>
  9. <exclusion>
  10. <groupId>group-c</groupId>
  11. <artifactId>excluded-artifact</artifactId>
  12. </exclusion>
  13. </exclusions>
  14. </dependency>
  15. <dependency>
  16. <groupId>group-a</groupId>
  17. <artifactId>artifact-b</artifactId>
  18. </dependency>
  19. </dependencies>
  20. </project>

projectB:

  1. <project>
  2. ...
  3. <dependencies>
  4. <dependency>
  5. <groupId>group-c</groupId>
  6. <artifactId>artifact-b</artifactId>
  7. <version>1.0</version>
  8. <type>war</type>
  9. <scope>runtime</scope>
  10. </dependency>
  11. <dependency>
  12. <groupId>group-a</groupId>
  13. <artifactId>artifact-b</artifactId>
  14. </dependency>
  15. </dependencies>
  16. </project>

总结:

  1. 项目中源代码使用的 jar 包一定在 pom.xml 中显示引用。
  2. 经常 check 一下包冲突,检查是否需要处理。
  3. 当使用多个模块时,parent 一定要使用包管理模块来规范 Jar 包版本,而不是包依赖模块直接引入依赖。
  4. 遇到冲突的时候第一步要找到maven加载的到时是什么版本的jar包,通过们mvn dependency:tree查看依赖树,通过maven的依赖原则来调整坐标在pom文件的申明顺序是最好的办法。

附:

推荐一个查看依赖关系和解决冲突好用的插件:Maven Helper
https://plugins.jetbrains.com/plugin/7179-maven-helper

参考资料

https://maven.apache.org/guides/getting-started/index.html

http://ifeve.com/maven-dependency-mechanism/

发表评论

表情:
评论列表 (有 0 条评论,345人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Maven依赖管理

    定义maven坐标 每个maven工程都需要定义本工程的坐标,坐标是maven对jar包的身份定义。 <!--项目名称,定义为组织名+项目名,类似包名-->

    相关 maven依赖机制依赖管理

    maven依赖机制及依赖管理 依赖性传递: 依赖调解: 当项目中出现多个版本构件依赖的情形,依赖调解决定最终应该使用哪个版本。当然,你也可以在项目POM文件中

    相关 Maven 依赖管理

    Maven 依赖管理 Maven 一个核心的特性就是依赖管理。当我们处理多模块的项目(包含成百上千个模块或者子项目),模块间的依赖关系就变得非常复杂,管理也变得很困难。针...