java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > maven依赖冲突

maven依赖冲突加载顺序与解决

作者:街一角

这篇文章主要介绍了项目中同时引用了相同依赖的不同版本,也就是冲突,maven 是如何选择的,了解了有助于解决项目中的依赖问题,需要的朋友可以参考下

依赖冲突加载顺序

介绍了项目中同时引用了相同依赖的不同版本,也就是冲突,maven 是如何选择的。了解了有助于解决项目中的依赖问题

先说结论:

优先级(运行子 pom):
<dependencyManagement> > 子 pom(直接依赖) > 父 pom > 间接依赖

直接依赖

        <!-- 直接依赖 -->
        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
            <version>2.2.0</version>
        </dependency>
        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
            <version>3.19.4</version>
        </dependency>

项目的 pom 文件直接引用依赖
结论:maven 会引用后申明的依赖

间接依赖

假设 module-starter 的 pom 如下:

        <dependency>
            <groupId>com.meizi</groupId>
            <artifactId>module4</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>com.meizi</groupId>
            <artifactId>module1</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

module4 引用 protobuf-java:3.11.4

module1 引用 protobuf-java:2.2.0

最终使用的是 protobuf-java:3.11.4

结论:间接依赖使用优先申明的

假设 module-starter 的 pom 如下:

        <dependency>
            <groupId>com.meizi</groupId>
            <artifactId>module2</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>com.meizi</groupId>
            <artifactId>module4</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

module4 引用 protobuf-java:3.11.4 (路径长度1)

module2 引用 module3 引用 protobuf-java:3.19.4(路径长度2)

最终使用的是 protobuf-java:3.11.4

结论:间接依赖使用路径长度最短的,如果长度一样,则优先申明的最终加载

父 pom 中的依赖

父 pom 如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.meizi</groupId>
    <artifactId>learnmaven</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <modules>
        <module>module1</module>
        <module>module2</module>
        <module>module3</module>
        <module>module4</module>
        <module>module-starter</module>
    </modules>

    <dependencies>
        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
            <version>3.11.4</version>
        </dependency>
    </dependencies>

</project>

module1 pom 如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>learnmaven</artifactId>
        <groupId>com.meizi</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>module1</artifactId>

    <dependencies>
        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
            <version>2.2.0</version>
        </dependency>

    </dependencies>

</project>

结论:子 pom 中的会覆盖父 pom 的依赖版本

版本锁定 <dependencyManagement>

    <!-- learnmaven 父pom-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.google.protobuf</groupId>
                <artifactId>protobuf-java</artifactId>
                <version>2.2.0</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

子模块 pom 可不用写版本
子模块中与 dependencyManagement 匹配的最小信息集是这四个 {groupId, artifactId, type, classifier},因为在大多数情况下都是 type=jar classifier=null,所以如果不写,maven默认,如果不是jar的需要指定。

        <!-- module-starter 子pom-->
        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
        </dependency>

子模块 pom 中间接依赖的版本也被锁死

        <!-- module-starter 子pom-->
        <dependency>
            <groupId>com.meizi</groupId>
            <artifactId>module4</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>com.meizi</groupId>
            <artifactId>module3</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

依赖冲突解决

了解了依赖冲突加载顺序,一定程度上可以解决冲突。 由于没有依赖传播级数的限制,会有可能出现循环依赖。 所以有一些方式来限制依赖传播

依赖调解(最短路径)

最短路径 项目的依赖树最近的依赖
如下依赖:

  A
  ├── B
  │   └── C
  │       └── D 2.0
  └── E
      └── D 1.0

会使用 D 1.0,因为他的路径最短,如果你想使用 D 2.0 可以在 A 项目中直接添加 D 2.0 依赖,如下

  A
  ├── B
  │   └── C
  │       └── D 2.0
  ├── E
  │   └── D 1.0
  │
  └── D 2.0 

版本锁定

<dependencyManagement>,使用见上文

依赖作用域

<scope> 作用域,限制依赖传递和决定何时依赖包含在类路径中

提供如下选项:

排除依赖

通过使用 exclusion 可以将不需要的依赖排除掉

        <dependency>
            <groupId>com.meizi</groupId>
            <artifactId>module4</artifactId>
            <version>1.0-SNAPSHOT</version>
            <exclusions>
                <exclusion>
                    <groupId>com.google.protobuf</groupId>
                    <artifactId>protobuf-java</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

此时,引入module4,将不会引入 protobuf-java

可选依赖

即 <optional>,默认false不可选,可传播; true 可选,可认为是被排除了,不可传播

        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
            <version>3.11.4</version>
            <!-- 默认false不可选,可传播; true 可选,可认为是被排除了,不可传播 -->
            <optional>true</optional>
        </dependency>

如果想排除此依赖,也可将 optional 设置为 true

依赖管理

导入依赖

在大型项目中,很难通过继承管理所有依赖,因为 maven 是单继承的。
为了解决这个,项目可以从其他项目导入。通过申明一个 type 是 pom,scope 是 import 的工件

        <!-- learnmaven 父pom-->
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>io.netty</groupId>
                    <artifactId>netty-bom</artifactId>
                    <version>4.1.29.Final</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>

所有 netty-bom 中 dependencyManagement 所管理的都会被合并过来。

        <!-- learnmaven 父pom-->
        <dependencyManagement>
            <dependencies>

                <dependency>
                    <groupId>io.netty</groupId>
                    <artifactId>netty-bom</artifactId>
                    <version>4.1.79.Final</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>

                <dependency>
                    <groupId>io.netty</groupId>
                    <artifactId>netty-bom</artifactId>
                    <version>4.1.29.Final</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>

如上,4.1.79.Final 将被使用,因为他先申明
并且导入是递归的,例如,netty-bom 导入了另一个 pom,那么这个项目也会导入

到此这篇关于maven依赖冲突加载顺序与解决的文章就介绍到这了,更多相关maven依赖冲突内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文