Maven的依赖管理

1、依赖的配置

1.1 坐标

Maven采用坐标来唯一标识一个构件,一组坐标包含以下元素:groupId、artifactId、version、packaging、classifier,其中groupId、artifactId、version是必须的,packaging是可选的,classifier是不能直接定义的。项目构件的名称一般为:artifactId-version[-classifier]. packaging

groupId:定义了当前项目所隶属的实际项目,一般一个公司或组织会有很多的实际项目,而一个实际项目下边又会包含很多的模块;

artifactId:定义了实际项目中的一个模块,一般会将实际项目名称作为artifactId的前缀;

version:定义了当前项目版本;

packaging:定义了Maven项目的打包方式,打包方式不同其构建的生命周期也会不同,默认的打包方式为jar;

classifier:定义了构建输出的一些附属构件,比如,Java文档、源代码等,该元素不能在项目中直接定义,因为附属构件不是由项目直接生成的,而是由附加的插件生成的。

1.2 依赖的配置

<project>
    ...
    <dependencies>
        <dependency>
            <groupId>group-a</groupId>
            <artifactId>artifact-a</artifactId>
            <version>1.0</version>
            <type>jar</type>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>group-c</groupId>
                    <artifactId>excluded-artifact</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>
</project>

根元素project下的dependencies可以包含一个或多个dependency元素,用于声明一个或多个依赖,每个dependency元素下可以包含如下元素:
groupId、artifactId、version:构件的基本坐标;
type:依赖的类型,对应于坐标中的packaging元素;
scope:依赖的范围,包括compile(默认)、provided、runtime、test、system、import(仅支持在dependencyManagement元素中依赖pom类型的依赖);
exclusions:用于排除传递性依赖。

1.3 依赖的范围

compile:编译依赖范围。默认的依赖范围,在没有指定时使用;对编译classpath、测试classpath、运行classpath都有效;具有传递性;

provided:已提供依赖范围。使用此依赖范围说明您希望JDK或者容器在运行时提供赖关系,例如,在web项目中使用的servlet-api,应将其设置为provided,因为web容器已提供了此依赖。该依赖范围仅对编译和测试的classpath有效,且不可传递;

test:测试依赖范围。此依赖范围的Maven依赖只对测试classpath有效,典型的依赖就是JUnit,它只在测试代码编译和执行测试的时候才可用;不具有传递性。

runtime:运行时依赖范围,该依赖范围表明该依赖不是编译所必需的,而是执行时所必需的,故此依赖范围只对于测试和运行的classpath有效,具有传递性。

system:系统依赖范围。该依赖范围与classpath的关系,和provided依赖范围完全一致,但是,此依赖不是通过Maven仓库解析的,而是与本机系统绑定的,所以在使用此依赖范围时必须通过systemPath元素显式地指定所依赖文件的路径。不具备传递性。

<dependency>
    <groupId>javax.sql</groupId>
    <artifactId>jdbc-stdext</artifactId>
    <version>2.0</version>
    <scope>system</scope>
    <systemPath>${java.home}/lib/rt.jar</systemPath>
</dependency>

import:导入依赖范围。该依赖范围不会对三种classpath产生实际的影响,它仅在dependencyManagement中的pom类型的依赖中使用。不具有传递性。
在这里插入图片描述

1.4 依赖的传递性

若Project-A依赖Project-B,而Project-B又依赖Project-C,则Project-C就是Project-A的一个传递性依赖。
在这里插入图片描述
在这里插入图片描述

2、依赖的解析

2.1 依赖的解析机制

<1> 当依赖的范围是system时,Maven会根据systemPath元素配置的路径信息从本地文件系统查找所需要的构件;
<2> 若依赖的范围不是system,则根据依赖的坐标计算仓库的路径,然后从本地仓库查找所需构件,若找到,则说明解析成功;
<3> 若本地仓库中没有找到所需构件,且所依赖构件的版本是正式版,则遍历所有的远程仓库,找到依赖后下载并解析使用;
<4> 若所依赖构件的版本是SNAPSHOT版,则基于更新策略读取所有远程仓库的元数据groupId/artifactId/version/maven-metadata.xml,将其与本地仓库的对应元数据合并后,得到最新的快照版本,然后根据此版本查找本地仓库,或从远程仓库下载。

2.2 依赖调解

Maven会自动解析所有项目的直接依赖和传递性依赖,并且根据相应的规则正确判断每个依赖的范围,对于一些依赖冲突,也能进行调解,以确保任何一个构件只有唯一的版本在依赖中存在。调解的原则如下:
第一原则:路径最近者优先。假设Project-A存在这样的依赖关系:Project-A -> Project-B -> Project-X(1.0),Project-A -> Project-C -> Project-D -> Project-X(2.0),则说明Project-X是Project-A的一个传递性依赖,并且Project-X有两个版本,Project-X(1.0)的路径长度为2,Project-X(2.0)的路径长度为3,此时Maven会解析使用Project-X(1.0);
第二原则:第一声明原则。若依赖路径的长度相等的情况下,在POM中依赖声明的顺序最靠前的那个依赖会被解析使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值