Maven权威指南(1):基本概念和依赖

发布时间 2023-07-22 19:43:42作者: 吃葡萄皮不吐葡萄

基本概念

标志 名称 说明
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>

如上面代码,groupIdartifactIdversion就是依赖组件的基本坐标信息
type:依赖的类型,对于项目坐标定义的packagine,一般不需要定义,默认为jar
scope: 依赖范围,默认为compile
optional:可选依赖,表示这个依赖是可选的,一般不建议使用
exclusions:排除依赖

依赖范围

背景

  1. Maven项目在编译、测试和运行的时候都会使用不同的classpath用于隔离不同场景下依赖的差异
  2. 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文件中的依赖),将那些间接依赖(直接依赖所依赖的组件,支持递归直接最底层的依赖),以传递性依赖的方式引入到当前项目中
好处:

  1. 不需要关心每个依赖所依赖的组件,Maven自动引入
  2. 不同依赖直接可能依赖同个组件,Maven可以自动减少重复引用

传递性依赖与依赖范围关系

compile test provided runtime
compile compile -- -- runtime
test tet -- -- test
provied provided -- -- provided
runtime runtime -- -- runtime

依赖调解

概念

当不同的直接依赖引入相同groupId和artifactId的间接依赖时,需要通过某种机制去确认具体该如何引入哪个直接依赖的间接依赖,这种机制就是依赖调解

规则

  1. 路径最近者最优
  2. 先声明者先使用
    例如:
  3. 存在这样的依赖关系:
    (1). A->B->C->X(1.0)
    (2). A->D->X(2.0)
    则会会通过(2)的方式引入X(规则1
  4. 存在这样的依赖关系:
    (1). A->B->X(1.0)
    (2). A->D->X(2.0)
    则会会通过(1)的方式引入X(规则2

可选依赖

概念:表示这个依赖是可选的,一般适用于标记多个相同类型但是不同实现的间接依赖,由使用方根据自己的需要再引入对应的实现,通过这种方式去按需引入直接需要的依赖
作用

  1. 可选的间接依赖不会直接引入到项目中,需要手动引入
  2. 按需引入间接依赖

排除依赖

代码模板

...
<dependency>
	<groupId>...</groupId>
	<artifactId>...</artifactId>
	<version>...</version>
	<exclusions>
		<exclusion>
			<groupId>...</groupId>
			<artifactId>...</artifactId>
		<exclusion>
	</exclusions>
</dependency>
...

作用:用于排除掉依赖中一些项目中不需要的间接依赖(可能因为依赖冲突、license违法、snapshot版本)
注意:声明exclusion时只需要groupId和artifactId即可,不需要version等信息,因为只需要这两个信息就可以唯一定位依赖图中的某个依赖

优化依赖

作用:排除多余的依赖,显示地声明某些必要的依赖
方法

  1. mvn dependency:list 查询当前项目的依赖
  2. mvn dependency:tree 查询挡墙项目的依赖树,可以直接看出某个依赖是如何引入的
  3. mvn dependency:analyze 自动分析项目中异常依赖(没有显式声明的依赖和未使用但是显式声明的依赖)
    注意:异常依赖需要人为确认、分析是否真的可以排除,因为有些代码是动态生产的,这种场景Maven无法分析到该jar包实际上是被引用了