maven依赖管理(依赖配置依赖传递依赖冲突依赖范围)

Posted 秃头披风侠.

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了maven依赖管理(依赖配置依赖传递依赖冲突依赖范围)相关的知识,希望对你有一定的参考价值。

文章目录

基本说明

这篇文章会介绍在maven中的依赖配置、依赖传递、依赖范围等知识点。


依赖配置

依赖配置很好理解,就是指当前项目需要什么jar,就在dependencies中进行配置

    <dependencies>
        <dependency>
            <!-- 组织名 -->
            <groupId>junit</groupId>
            <!-- 项目名 -->
            <artifactId>junit</artifactId>
            <!-- 版本号 -->
            <version>4.13.2</version>
        </dependency>
    </dependencies>

依赖传递

在maven管理jar的时候,冲突是肯定存在的,这里就来介绍一下在maven中对于jar的一些管理是如何进行的,遵循什么规则。


直接依赖

简单说就是我们在A项目中引入了B,那么就称A直接依赖于B

这个项目中引入了junit,那么改项目就直接依赖于junit


间接依赖

如果项目A依赖于项目B,而项目B又依赖于项目C,我们就称项目A间接依赖于项目C

当前项目依赖于junit,junit又依赖于hamcrest-core,所以当前项目就间接依赖于hamcrest-core


依赖冲突

当我们引入了A和B,A项目中又引入B,那么这时项目中就有了2个B,于是就会产生依赖冲突,当然还有其他很多情况也会产生依赖冲突。这里就是说明一些依赖冲突时的优先原则。

路径优先

当依赖中出现相同的资源时,层级越深,优先级越低,层级越浅,优先级越高

我们在项目中同时引入junit和hamcrest-core来测试一下

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
        </dependency>
        <dependency>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest-core</artifactId>
            <version>2.2</version>
        </dependency>

可以发现,根据路径优先原则,junit引入的hamcrest-core就被覆盖掉了


声明优先

当资源在相同层级被依赖时,配置顺序靠前的覆盖配置顺序靠后的

我创建了2个maven模块,都引入了junit,只不过是不同的版本,现在来测试一下

        <dependency>
            <groupId>com.ttpfx</groupId>
            <artifactId>maven2</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.ttpfx</groupId>
            <artifactId>maven3</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

我同时引入了自己创建的2个模块,现在来看看junit的版本

由于maven2在前面,所以就是引入的junit 4.13.2

现在讲maven3放在前面再来进行测试

        <dependency>
            <groupId>com.ttpfx</groupId>
            <artifactId>maven3</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.ttpfx</groupId>
            <artifactId>maven2</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

可以发现再相同层级的时候,就是顺序靠前的覆盖配置顺序靠后的


特殊依赖

当同级配置了相同资源的不同版本(没有意义的配置),后配置的覆盖先配置的

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
        </dependency>

上面这样配置,此时引入的junit版本为4,11

这样写idea会给出提示


可选依赖

可选依赖指对外隐藏当前所依赖的资源,也就是只有当前项目可以使用

下面我创建了一个模块 maven4,引入了2个jar

现在我再另外一个模块maven1引入了前面创建的模块 maven4。

        <dependency>
            <groupId>com.ttpfx</groupId>
            <artifactId>maven4</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

此时maven1就会同时引入maven4的2个依赖

如果我们不想让其他项目引用某个依赖,我们可以使用option来进行指定

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <!-- 默认为false,如果指定为ture,那么改依赖不会进行依赖传递,即隐藏 -->
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.49</version>
        </dependency>

我们吧maven4中的junit的option设置为了true,那么再maven1中就不会有junit依赖了


排除依赖

排除依赖指主动排除依赖的资源, 被排除的资源无需指定版本。

我们知道,当我们引入junit的时候会间接引入一个hamcrest-core

如果我们就是不想引入这个jar,那么就可以使用exclusions来进行排除

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <exclusions>
                <!-- 可以有多个exclusion -->
                <exclusion>
                    <groupId>org.hamcrest</groupId>
                    <artifactId>hamcrest-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

这样我们就可以排除掉hamcrest-core

此时项目中就没有hamcrest-core了(当然,此时使用junit会报错,因为junit依赖于hamcrest-core)


可选依赖和排除依赖区别

简单说就是: 可选(隐藏)依赖是不让其他项目来引用(我不给), 排除依赖是主动不要引入的某个资源(我不要)


依赖范围

我们可以通过scope来指定依赖作用范围,作用范围有compile(默认)、test、provided、runtime。它们的作用范围如下:


下面就列举了2个常见的情形

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <!-- 只用于测试 -->
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <!-- 不会参与打包 -->
            <scope>provided</scope>
        </dependency>

还需要说明的是,主代码表示 src/main 文件夹下的代码,测试代码表示 src/test 目录下面的代码


总结

在这篇文章中介绍了maven中的一些基础概念,maven的依赖传递规则,出现冲突的一些处理等,具体可以参考官方文档

04_项目一众筹00_05Maven依赖概念,依赖范围依赖传递性依赖的原则:解决jar包冲突依赖排除统一版本管理

Maven概念_目录

依赖范围





依赖传递性


具体例子:先跟上一篇文章那样,创建一个新的Maven项目


然后再建一个C
最后我们来实现他们的依赖关系


同理后面的 B依赖于C也是这样做




这个我们可以验证一下,我们会发现test的依赖范围确实不具有依赖性



依赖的原则:解决jar包冲突

像上面的例子,如果我们是都传递给A的,那么会不会有冲突呢

其实不用担心,Maven里面遵循这几个原则:

依赖排除

依赖排除是啥意思,意思就是这包我不想要,你别传递给我



只要隔断B,自然A就不会传递了,所以我们只需要处理B就行了



如果是自己配置了,不排除依赖也行,为啥呢?因为自己配置的路径最短,不影响

统一版本管理



以上是关于maven依赖管理(依赖配置依赖传递依赖冲突依赖范围)的主要内容,如果未能解决你的问题,请参考以下文章

04_项目一众筹00_05Maven依赖概念,依赖范围依赖传递性依赖的原则:解决jar包冲突依赖排除统一版本管理

如何快速的解决Maven依赖冲突

Maven依赖传递依赖传递排除依赖冲突

Maven依赖传递依赖传递排除依赖冲突

Maven依赖传递和冲突解决

maven的依赖传递及冲突