Maven 依赖
根元素 project
下的 dependencies
可以包含一个或多个dependency
元素,以声明一个或者多个项目依赖。每个依赖可以包含的元素有:
groupId
,artifactId
,version
:依赖的基本坐标type
:依赖的类型,大部分情况下不必声明,默认为jarscope
:依赖的范围optional
:标记依赖是否可选exclusions
:用来排除传递性依赖
依赖范围
首先要弄清楚,Maven在不同的时候,使用了不同的classpath。Maven在编译项目主代码的时候使用compile classpath;在编译和执行测试的时候使用test classpath;在实际运行Maven项目的时候使用runtime classpath。
依赖范围
就是用来控制依赖于这三种classpath(compile classpath, test classpath, runtime classpath)的关系。Maven有以下几种依赖范围:
compile
:编译依赖范围,如果没有指定,默认使用该依赖范围test
:测试依赖范围,使用此依赖范围的Maven依赖,只对test classpath有效provided
:已提供依赖范围,使用此依赖范围的Maven依赖,对于compile和test classpath有效,但在运行时无效runtime
:运行时依赖范围,使用此依赖范围的Maven依赖,对于test和runtime classpath有效,但在编译主代码时无效system
:系统依赖范围,其与三种classpath的关系,和provided依赖范围一致
依赖范围与三种classpath的关系如下所示:
依赖范围Scope | 对于compile classpath有效 | 对于test classpath有效 | 对于runtime classpath有效 | 例子 |
---|---|---|---|---|
compile | Y | Y | Y | spring-core |
test | Y | JUnit | ||
provided | Y | Y | servlet-api | |
runtime | Y | Y | JDBC驱动实现 | |
system | Y | Y | 本地的Maven仓库职位的类库文件 |
传递性依赖
假设A依赖于B,B依赖于C,则A对于B是第一直接依赖,B对于C是第二直接依赖,A对于C是传递性依赖
。第一直接依赖和第二直接依赖决定了传递性依赖的范围,如下表所示,最左边一列表示第一直接依赖范围,最上面一行表示第二直接依赖范围,中间的交叉单元格则表示传递性依赖范围。
/ | compile | test | provided | runtime |
---|---|---|---|---|
compile | compile | / | / | runtime |
test | test | / | / | test |
provided | provided | / | provided | provided |
runtime | runtime | / | / | runtime |
依赖仲裁
Maven依赖仲裁(Dependency Mediation):
- 第一原则:最短路径优先原则
- 第二原则:第一声明优先原则,在依赖路径长度相等的前提下,在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,在主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权威指南