MAVEN依赖管理
MAVEN 一个核心的特性就是依赖管理。当我们处理多模块的项目,模块间的依赖关系就变得非常复杂,管理也变得很困难。针对此种情形,MAVEN 提供了一种高度控制的方法。
一、功能介绍
功能 | 描述 |
---|---|
依赖调节 | 当一个依赖的多个的版本同时出现时,决定哪个依赖版本将会被使用 |
依赖管理 | 任何依赖版本可以通过"dependencyManagement"元素预先显示声明 |
依赖范围 | 决定依赖传递的作用域(可传递性、作用时机等) |
依赖排除 | 任何可传递的依赖都可以通过 "exclusion" 元素被排除在外 |
依赖可选 | 任何可传递的依赖都可以通过 "optional" 元素被标记为可选的 |
(一)依赖调节
依赖调节功能又可以叫版本冲突解决自动/默认策略:
1、最短路径优先:计算依赖传递深度,初始为当前项目。
例如:项目A引入的资源X,通过命令mvn dependency:tree
查看依赖树关系,有X(1.0)与X(2.0)两个版本
(1)A→B→C→X(1.0)
(2)A→D→X(2.0)
基于最短路径优先原则,会自动选择X(2.0)生效。
2、最先申明优先:当依赖深度相同时,取决于pom.xml中资源的引入先后顺序。
特别提示:通过"parent"元素指定工程的pom.xml定义的资源与当前项目pom.xml定义的资源依赖深度相同,但后者的申明顺序视为先于前者。
(二)依赖管理
依赖管理功能是通过预先申明可能需要引入的资源依赖配置实现,通常在项目的公共依赖pom.xml中,通过"dependencyManagement"元素申明。常见的有两种形式:
1、直接申明需要引入的资源配置
<dependencyManagement>
<dependencies>
<dependency>
<groupId>cn.histo</groupId>
<artifactId>ecp-common</artifactId>
<version>${ecp.project.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
2、间接引入其他依赖管理配置pom.xml
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
通过在公共依赖pom.xml中预先申明,在项目工程子模块中的传递性依赖或者没有指定版本的依赖资源都采用依赖配置申明的版本。
(三)依赖范围
MAVEN的依赖范围配置见下方"scope"元素:
<dependency>
<groupId>资源组</groupId>
<artifactId>资源名</artifactId>
<version>资源版本号</version>
<scope>依赖范围</scope>
</dependency>
包含如下几种可选范围:
1、compile(默认):编译依赖范围,对于编译、测试、运行三阶段都有效。即在编译、测试、运行时都需要依赖该资源时采用;
2、test:测试依赖范围,只对测试阶段有效。即仅需在测试时需要依赖该资源时采用,例如:junit;
3、provided:已提供依赖范围,编译和测试阶段有效,运行阶段无效。通常对容器、运行环境资源的依赖采用,例如servlet-api,在项目运行时,tomcat等容器已经提供,无需MAVEN重复引入;
4、runtime:运行时依赖范围,测试和运行有效,编译无效。通常对类似驱动性质资源的依赖采用,例如jdbc驱动实现,编译阶段只需接口,测试或运行时才需要具体的jdbc驱动实现;
5、system:系统依赖范围。该范围的依赖时必须通过systemPath元素显示地指定依赖文件的路径,不依赖Maven仓库解析,所以可能会造成建构的不可移植,谨慎使用。
6、import:导入依赖范围。该范围的依赖资源只在一个pom.xml文件中定义使用,例如:依赖范围管理方式2(间接引入其他依赖管理配置pom.xml )。
以下描述了依赖范围与生效阶段的对应关系:
依赖范围 | 编译有效 | 测试有效 | 运行有效 | 例子 |
---|---|---|---|---|
compile | Y | Y | Y | Spring-core |
test | - | Y | - | Junit |
provided | Y | Y | - | Servlet-api |
runtime | - | Y | Y | Jdbc驱动 |
system | Y | Y | - | 本地的Maven之外资源 |
import | Y | - | - | 间接引入其他以来管理配置pom.xml |
(四)依赖排除
MAVEN的依赖排除配置见下方"exclusions"元素:
<dependency>
<groupId>cn.histo</groupId>
<artifactId>ecp-common</artifactId>
<exclusions>
<exclusion><!--排除不需要的依赖-->
<groupId>org.springblade</groupId>
<artifactId>blade-core-launch</artifactId>
</exclusion>
</exclusions>
</dependency>
(五)依赖可选
MAVEN的依赖可选配置见下方"optional"元素:
<!-- Oracle -->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc7</artifactId>
<optional>true</optional>
</dependency>
<!-- PostgreSql -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<optional>true</optional>
</dependency>
当依赖中optional属性为true时,表示该依赖为可选依赖,并且将不会被传递。也就是说该依赖只用于当前项目。
二、最佳实践
为了能够更清晰的阐述MAVEN依赖管理的实践方案,现对项目工程引入的依赖资源,按照其掌控程度进行包引入分类:
1、一方包:工程内各模块相互依赖的资源。只要拥有项目工程的权限,就具备所有一方包的调整能力(掌控程度最高);
2、二方包:公司内部的共享的依赖库资源,一般指公司内部其他项目工程发行的依赖资源,通常由公司职员维护更新(掌控程度中等);
3、三方包:公司之外的开源库,比如apache、alibaba、google等发行的依赖资源,通常由开源社区人员维护更新(掌控程度最低)。
MAVEN依赖管理最佳实践准则:
1、准则一:项目包引入顺序
(1)common包永远作为第一位引入;
(2)一方包作为第二顺位引入;
(3)二方包作为第三顺位引入;
(4)三方包最后引入。
2、准则二:模块公共包引入限制
(1)禁止一方包引入;
(2)禁止依赖可选包(optional = true)引入;
3、准则三:待补充
全部评论