maven 依赖管理最佳实践

2018-05-20 23:03:59   最后更新: 2018-05-20 23:03:59   访问数量:1890




maven 是一个常用的 java 跨平台项目管理工具,主要工作是项目构建、依赖管理和项目信息管理

除了编写源代码,我们每天有相当一部分时间花在了编译、运行单元测试、生成文档、打包和部署等繁琐而不起眼的工作上,这就是项目的构建过程

而 maven 可以自动地从清理、编译、测试到生成报告、打包、部署,极大的简化了我们日常的工作,同时它还是一个依赖管理工具和项目信息管理工具,提供了中央仓库,能帮助我们自动下载构件

作为 java 程序员必备的工具,深入研究和了解 maven 的使用是非常重要的,尤其是在构建失败、包冲突解决时,只有了解了我们即将介绍的 maven 工具的用法和要点才不会一筹莫展

通过 maven 进行项目的配置和构建过程我们曾经介绍过:

maven 基本介绍及项目创建

本文我们就来重点介绍一下 maven 作为依赖管理和项目信息管理工具的使用

 

maven 最强大的功能就是项目中依赖的管理

根元素 project 下的 dependencies 可以包含一个或多个 dependency 元素,以声明一个或者多个项目依赖

<dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> <scope>test</scope> </dependency>

 

 

如上所示,maven 依赖由以下几个元素构成:

元素是否必须备注
groupId、artifactId、versionmaven 依赖的基本坐标
tpye依赖的类型,默认为 jar
scope依赖的范围
optional标记依赖是否可选
exclusions排除传递性依赖选项

 

maven 在不同的阶段,使用的包加载路径是不同的

  • 编译项目主代码时使用 compile classpath
  • 编译和执行测试时使用 test classpath
  • 在实际运行Maven项目时使用 runtime classpath

 

依赖范围就是用来控制依赖于这三种 classpath 的关系的,maven 有以下几种依赖范围可供选择:

  • compile -- 编译依赖范围,如果没有指定,默认使用该依赖范围
  • test -- 测试依赖范围,使用此依赖范围的 maven 依赖,只对 test classpath 有效
  • provided -- 已提供依赖范围,使用此依赖范围的 maven 依赖,对于 compile 和 test classpath 有效,但在运行时无效
  • runtime -- 运行时依赖范围,使用此依赖范围的 maven 依赖,对于 test 和 runtime classpath 有效,但在编译主代码时无效
  • system -- 系统依赖范围,其与三种 classpath 的关系,和 provided 依赖范围一致

 

依赖范围Scope对于compile classpath有效对于test classpath有效对于runtime classpath有效例子
compileYYYspring-core
test Y JUnit
providedYY servlet-api
runtime YYJDBC 驱动实现
systemYY 本地的 maven 仓库之类的类库文件

 

依赖范围的传递性

如果 A 依赖 B,B 依赖 C,那么 C 对于 A 就是传递性依赖

下表列出了依赖范围的传递性:

第一依赖
compiletestprovidedruntime
第二依赖compilecompile//runtime
testtest//test
providedprovided/providedprovided
runtimeruntime//runtime

 

maven 依赖仲裁(Dependency Mediation)遵循以下两个原则:

  1. 最短路径优先原则
  2. 第一声明优先原则,在依赖路径长度相等的前提下,在POM中依赖声明最靠前的依赖优先

 

例如,项目A有这样的依赖关系:

1. A -> B -> C -> X(1.0),A -> D -> X(2.0),X(1.0) 路径长度为 3,X(2.0) 路径长度为 2,根据第一原则,X(2.0) 会被解析使用;

2. A -> B -> Y(1.0),A -> C -> Y(2.0),Y(1.0) 和 Y(2.0) 的依赖路径长度相同,如果 B 的依赖声明在C之前,那么 Y(1.0) 会被解析使用。

 

  • mvn dependency:list -- 列出最终确定的依赖
  • mvn dependency:tree -- 打出依赖树
  • mvn dependency:analyze -- 依赖分析,给出项目中已使用但未声明的依赖,以及未使用但已声明的依赖

 

依赖管理

  • 多模块项目中,定义一个主 pom,在主 pom 中使用 dependencyManagement 定义依赖、版本和依赖排除
  • 子模块从主 pom 中继承依赖,一般情况下,不要在子模块中做依赖排除,也不要指定依赖版本

 

归类依赖

如果多个相关的依赖的版本都是相同的,可以使用 properties 元素定义 maven 属性,依赖的版本值用这一属性引用表示

<properties> <spring.version>2.5.6</spring.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> </dependencies>

 

 

Maven实战(Maven in Action)

Maven权威指南

Maven重要概念及最佳实践 -- https://segmentfault.com/a/1190000000640821

Maven依赖范围及传递 -- https://blog.csdn.net/stypace/article/details/38440545

 

 

欢迎关注微信公众号,以技术为主,涉及历史、人文等多领域的学习与感悟,每周三到七篇推文,只有全部原创,只有干货没有鸡汤

 






技术帖      龙潭书斋      技术分享      java      spring      maven      jar      war      dependency     


京ICP备2021035038号