maven学习(2):依赖

本文详细介绍了Maven的依赖管理,包括依赖的导入方式、详细配置、依赖范围(如compile、test、provided、runtime)及其作用,依赖的传递性规则,以及如何通过exclusions标签排除不需要的依赖。此外,还讨论了依赖冲突的解决策略,包括跨pom文件冲突和同一pom文件内的冲突。最后,解释了optional属性在依赖传递中的作用。
摘要由CSDN通过智能技术生成

一、什么是依赖

        每当我们需要使用某个框架时,比如 SpringMVC,那么我们需要导入相应的 jar 包,但是手动导入包的时候,往往会漏掉几个 jar 包,那么在使用该框架的时候系统就会报错。那么我们就说导入的包与未导入的包存在依赖关系。而使用 Maven 我们只需要在 pom.xml 文件中进行相应的配置,它就会帮助我们自动管理 jar 包之间的依赖关系。

二、依赖的详细配置

        我们以 Junit 为例,在 pom.xml 文件中进行详细而完整的配置。

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <type>...</type>
        <scope>...</scope>
        <optional>...</optional>
        <exclusions>     
            <exclusion>     
                <groupId>...</groupId>     
                <artifactId>...</artifactId>     
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>
  • dependencies:一个 pom.xml 文件中只能存在一个这样的标签。用来管理依赖的总标签。
  • dependency:包含在dependencies标签中,可以有无数个,每一个表示一个依赖
  • groupId、artifactId和version:依赖的基本坐标,对于任何一个依赖来说,基本坐标是最重要的,Maven根据坐标才能找到需要的依赖。
  • type:依赖的类型,对应于项目坐标定义的packaging。大部分情况下,该元素不必声明,其默认值是jar。
  • scope:依赖的范围,默认值是 compile。后面会进行详解。
  • optional:标记依赖是否可选。
  • exclusions:用来排除传递性依赖,后面会进行详细介绍。

三、依赖的范围

        一般情况下,我们对前面三个依赖用的比较多。

  • 主程序目录结构 src/main/java
  • 测试程序目录结构:src/test/java

1、compile 范围依赖

  • 对主程序是否有效:有效
  • 对测试程序是否有效:有效
  • 是否参与打包:参与
  • 是否参与部署:参与
  • 典型例子:log4j   

2、test 范围依赖

  • 对主程序是否有效:无效
  • 对测试程序是否有效:有效
  • 是否参与打包:不参与
  • 是否参与部署:不参与
  • 典型例子:Junit

3、provided 范围依赖

  • 对主程序是否有效:有效
  • 对测试程序是否有效:有效
  • 是否参与打包:不参与
  • 是否参与部署:不参与

        典型例子:servlet-api.jar,一般在发布到服务器中,比如 tomcat,服务器会自带servlet-api.jar 包,所以provided 范围依赖只在编译测试有效。

4、runtime 范围依赖

        在测试、运行的时候依赖,在编译的时候不依赖。例如:JDBC驱动,项目代码只需要jdk提供的jdbc接口,只有在执行测试和运行项目的时候才需要实现jdbc的功能。

四、依赖的传递

        比如我们创建三个Maven工程,maven-first、maven-second以及maven-third,而third依赖于second,second又依赖于first,那么我们说 second 是 third 的第一直接依赖,first是second的第二直接依赖。而first是third的间接依赖。

        依赖之间的传递如下图:第一列表示第一直接依赖,第一行表示第二直接依赖

  1. 当第二依赖的范围是compile的时候,传递性依赖的范围与第一直接依赖的范围一致。
  2. 当第二直接依赖的范围是test的时候,依赖不会得以传递。
  3. 当第二依赖的范围是provided的时候,只传递第一直接依赖范围也为provided的依赖,且传递性依赖的范围同样为 provided;
  4. 当第二直接依赖的范围是runtime的时候,传递性依赖的范围与第一直接依赖的范围一致,但compile例外,此时传递的依赖范围为runtime;

        例如:创建3个maven工程。 

     在first-maven的pom.xml中配置

        然后second-maven依赖fisrt-maven,third-maven依赖second-maven,其pom.xml 文件如下:

        second-maven的 pom.xml

        third-maven的 pom.xml

        我们发现在 third-maven和 second-maven都没有 first-maven引入的 Junit 包,正好符合上面总结的第二点:当第二直接依赖的范围是test的时候,依赖不会得以传递。

        第二依赖范围是compile。如果我们将 first-maven的Junit 改为 compile,那么将会符合上面总结的第一点:当第二依赖的范围是compile的时候,传递性依赖的范围与第一直接依赖的范围一致。

五、依赖的排除

        如果我们在当前工程中引入了一个依赖是 A,而 A 又依赖了 B,那么 Maven 会自动将 A 依赖的 B 引入当前工程,但是个别情况下 B 有可能是一个不稳定版,或对当前工程有不良影响。这时我们可以在引入 A 的时候将 B 排除。

        比如:我们在first-maven中添加 spring-core,maven 会自动将 commons-logging添加进来,那么由于 second-maven是依赖 first-maven  的,那么 second-maven  中将存在 spring-core(自带了commons-logging),这时候我们不想要 commons-logging,那该怎么办呢?我们上面第二大点提到了:

        如何排除呢?我们在 second-maven 的 pom.xml 文件中添加如下代码:

六、依赖的冲突

        在maven中存在两种冲突方式:一种是跨pom文件的冲突,另一种是同一个pom文件中的冲突。

        跨 pom 文件,路径最短者优先。比如我们在 first-maven中的 Junit 是4.12版本的,second-maven中的 Junit 是4.10版本的,那么third-maven 中的 Junit 将会是那个版本呢?

        由上图我们可以看出,由于 second-maven 是 third-maven的直接依赖,明显相比于 first-maven路径要短,所以 third-maven的 Junit 版本与 second-maven 保持一致。

        同一个pom.xml 文件,先申明者优先。

七、可选依赖

        Optional标签标示该依赖是否可选,默认是false。可以理解为,如果为true,则表示该依赖不会传递下去,如果为false,则会传递下去。

        我们是在 second-maven的 pom 文件中设定 Junit 不可传递,那么 third-maven工程中将不会有来自 second-maven 的 Junit 的传递。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

游王子og

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值