依靠抵触加载次序

介绍了项目中一起引证了相同依靠的不同版别,也便是抵触,maven 是怎么选择的。了解了有助于处理项目中的依靠问题

先说定论:

  • 直接依靠的会引证后声明的依靠
  • 直接依靠运用途径长度最短的,假如长度相同,则优先声明的终究加载
  • 有父 pom 的子 pom 中的会掩盖父 pom 的依靠版别
  • <dependencyManagement> 办理的版别,子模块 pom 中直接依靠的版别也被锁死

优先级(运行子 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>

maven依靠抵触加载次序与处理

项目的 pom 文件直接引证依靠
定论:maven 会引证后声明的依靠

  1. 这种情况简直不会有,谁会在一处一起声明2个相同依靠不同版别的依靠,倘若呈现了,了解即可。

直接依靠

假定 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>

maven依靠抵触加载次序与处理

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>

maven依靠抵触加载次序与处理

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>

maven依靠抵触加载次序与处理

定论:子 pom 中的会掩盖父 pom 的依靠版别

  1. 假如直接依靠和父 pom 中的依靠呈现,以父 pom 优先

版别确定 <dependencyManagement>

  • 运用
    如下在父 pom 声明:

        <!-- 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>
    

    maven依靠抵触加载次序与处理

    从可传达依靠并入的依靠的版别也受此约束。

依靠抵触处理

了解了依靠抵触加载次序,一定程度上能够处理抵触。 由于没有依靠传达级数的约束,会有或许呈现循环依靠。 所以有一些方式来约束依靠传达

依靠调解(最短途径)

最短途径 项目的依靠树最近的依靠
如下依靠:

  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> 效果域,约束依靠传递和决议何时依靠包括在类途径中

供给如下选项:

  • compile 默许,编译依靠项在项目的一切类途径中都可用。此外,这些依靠关系被传达到依靠的项目。
  • runtime 在编译中不需要,在履行中需要
  • test 标明该依靠在正常运用中不是有必要的,而且仅在测验编译和履行阶段可用,这个效果域不是可传递的
  • system 除了您有必要供给显式包括它的JAR之外,此效果域与供给的效果域类似。工件总是可用的,不会在存储库中查找。
  • provided 类似compile,标明这个依靠是供给的,在运行时会有外部供给(例如tomcat),仅在编译和测验,是不行传递的
  • import 只用在pom的 <dependencyManagement> 部分,它指示该依靠项将被指定POM的<dependencyManagement>部分中的有效依靠项列表所替换。

排除依靠

经过运用 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,那么这个项目也会导入

bom poms

Bill of Materials (BOM) 资料清单

参考文献

  1. maven.apache.org/guides/intr…