Maven依赖传递和冲突解决

北城以北 提交于 2020-01-29 16:40:24

如下面,一个典型的Maven依赖配置格式。

<dependencies>
  <dependency>
    <groupId></groupId>
    <artifactId></artifactId>
    <version>版本</version>
    <type>依赖的类型,对应于项目的packing,默认是jar</type>
    <scope>依赖范围</scope>
    <systemPath>配合scope=system时使用</systemPath>
    <optional>标记是否为可选依赖</optional>
    <exclusions>
      用来排除传递性依赖
      <exclusion>
      </exclusion>
    </exclusions>
  </dependency>
</dependencies>

今天想到Maven的依赖传递,和冲突的解决尚有疑惑,比如scope的如何决定依赖传递,冲突时maven的默认解决是什么,如何调节?

依赖范围

Maven的依赖范围一共有:

  • compile,默认,对于编译、测试、运行范围有效
  • runtime,对运行范围有效,典型如JDBC类库这种接口与实现项分离的类库,在编译时仅依赖相关的接口,在具体运行时,才需要具体的mysql/oracle等驱动程序
  • privoded,对编译、测试范围有效;典型的如servlet-api,运行时由容器提供
  • system,与provided一样,但必须显示指定依赖文件,通过
  • test,对测试范围有效

  • import,不对任何范围有效,只能在dependencyManagement中使用

依赖传递

compile runtime provided test
compile compile runtime - -
runtime runtime runtime - -
provided provided provided provided -
test test test - -

每个不同的作用范围以不同的方式影响依赖传递。如上面表格以A项目为例:

左列为 A->B(compile)第一关系(直接依赖):A依赖B compile

横列为 B->C(compile)第二关系(传递依赖):B依赖C compile

交叉即最终的传递性依赖范围,未列出的将被忽略。

依赖冲突

依赖传递,必然会出现依赖冲突,冲突调节有两个原则:

  1. 最短路径原则

    比如A->B->C-D(1.0),A-C-D(2.0),则选择D(2.0)

  2. 最先声明原则

    比如A->B->D(1.0),A-C-D(2.0),则选择D(1.0)

可以自己使用mvn dependency:tree命令试试,idea用户直接使用Maven Helper插件。

对于冲突的解决,可以手动介入,使用exclusions一个个解决冲突的jar

<dependency>
  <groupId>sample.ProjectB</groupId>
  <artifactId>Project-B</artifactId>
  <version>1.0-SNAPSHOT</version>
  <exclusions>
    <exclusion>
      <groupId>sample.ProjectE</groupId> <!-- Exclude Project-E from Project-B -->
      <artifactId>Project-E</artifactId>
    </exclusion>
  </exclusions>
</dependency>

依赖管理

项目中使用Springboot有两种方式,

一种是使用继承父类

<!-- Inherit defaults from Spring Boot -->
<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.1.11.RELEASE</version>
</parent>

另一种则是使用了dependencyManagement

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-dependencies</artifactId>
      <version>2.1.11.RELEASE</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

这两种都可以限定当前项目和子项目使用既定的版本,因此依赖时不需要指定version

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
  <groupId>de.codecentric</groupId>
  <artifactId>spring-boot-admin-starter-client</artifactId>
</dependency>
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!