基本概念
标志 | 名称 | 说明 |
---|---|---|
groupId | 组信息 | 表示这个项目所在的组织或者公司信息 |
artifactId | 唯一Id | 表示这个项目在组中的唯一Id |
version | 版本信息 | 表示这个项目迭代的版本 |
packaging | 打包方式 | 定义这个项目的打包方式,默认值为jar,常见值有jar、war、pom |
classifier | 附属构件 | 定义构件输出的附属构件,例如项目的javadoc和source包,该字段无法直接定义 |
name | 名称 | 项目的友好名称,方便查阅 |
项目构件的文件名:artifactId-version[-classifier].packaging
Maven坐标体系
元素:groupId,artificatId,version,packaging,classifier
通过以上五个元素就可以在仓库中唯一确定一个Maven组件
例如:
我们要查找Java5的TestNG的5.8版本,这个时候它的五元素就是
字段 | 值 |
---|---|
groupId | org.testng |
artificatId | testng |
version | 5.8 |
packaging | jar |
classifier | jdk15 |
注意:大部分时候可以省略packaging和classifier
Maven 依赖
配置
基础代码如下:
<project>
...
<dependencies>
<dependency>
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>...</version>
<type>...</type>
<scope>...</scope>
<optional>...</optional>
<exclusions>
<exclusion>...</exclusion>
....
</exclusions>
</denpendenc>
</dependencies>
...
</project>
如上面代码,groupId、artifactId、version就是依赖组件的基本坐标信息
type:依赖的类型,对于项目坐标定义的packagine,一般不需要定义,默认为jar
scope: 依赖范围,默认为compile
optional:可选依赖,表示这个依赖是可选的,一般不建议使用
exclusions:排除依赖
依赖范围
背景
- Maven项目在编译、测试和运行的时候都会使用不同的classpath用于隔离不同场景下依赖的差异
- java中classpath可以理解为java程序所需要的依赖包,也就是常见的lib概念
classpath种类
编译classpath、测试classpath、运行classpath
依赖范围种类
名称 | 说明 | claspath作用范围 |
---|---|---|
compile | 编译依赖范围,默认范围 | 编译classpath、测试classpath、运行classpath |
test | 测试依赖范围 | 测试classpath |
provided | 已提供依赖范围 | 编译classpath、测试classpath |
runtime | 运行时依赖范围 | 测试classpath、运行classpath |
system | 系统依赖范围 | 编译classpath、测试classpath |
import | 导入依赖范围 | 不会影响classpath |
注意:
system的依赖范围需要和systemPath一起使用,通过systemPath定义依赖文件的路径
传递性依赖
概念
Maven会解析各个直接依赖(也就是直接定义在项目pom.xml文件中的依赖),将那些间接依赖(直接依赖所依赖的组件,支持递归直接最底层的依赖),以传递性依赖的方式引入到当前项目中
好处:
- 不需要关心每个依赖所依赖的组件,Maven自动引入
- 不同依赖直接可能依赖同个组件,Maven可以自动减少重复引用
传递性依赖与依赖范围关系
compile | test | provided | runtime | |
---|---|---|---|---|
compile | compile | -- | -- | runtime |
test | tet | -- | -- | test |
provied | provided | -- | -- | provided |
runtime | runtime | -- | -- | runtime |
依赖调解
概念
当不同的直接依赖引入相同groupId和artifactId的间接依赖时,需要通过某种机制去确认具体该如何引入哪个直接依赖的间接依赖,这种机制就是依赖调解
规则
- 路径最近者最优
- 先声明者先使用
例如: - 存在这样的依赖关系:
(1). A->B->C->X(1.0)
(2). A->D->X(2.0)
则会会通过(2)的方式引入X(规则1) - 存在这样的依赖关系:
(1). A->B->X(1.0)
(2). A->D->X(2.0)
则会会通过(1)的方式引入X(规则2)
可选依赖
概念:表示这个依赖是可选的,一般适用于标记多个相同类型但是不同实现的间接依赖,由使用方根据自己的需要再引入对应的实现,通过这种方式去按需引入直接需要的依赖
作用:
- 可选的间接依赖不会直接引入到项目中,需要手动引入
- 按需引入间接依赖
排除依赖
代码模板
...
<dependency>
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>...</version>
<exclusions>
<exclusion>
<groupId>...</groupId>
<artifactId>...</artifactId>
<exclusion>
</exclusions>
</dependency>
...
作用:用于排除掉依赖中一些项目中不需要的间接依赖(可能因为依赖冲突、license违法、snapshot版本)
注意:声明exclusion时只需要groupId和artifactId即可,不需要version等信息,因为只需要这两个信息就可以唯一定位依赖图中的某个依赖
优化依赖
作用:排除多余的依赖,显示地声明某些必要的依赖
方法:
mvn dependency:list
查询当前项目的依赖mvn dependency:tree
查询挡墙项目的依赖树,可以直接看出某个依赖是如何引入的mvn dependency:analyze
自动分析项目中异常依赖(没有显式声明的依赖和未使用但是显式声明的依赖)
注意:异常依赖需要人为确认、分析是否真的可以排除,因为有些代码是动态生产的,这种场景Maven无法分析到该jar包实际上是被引用了