Maven之依赖管理

本文详细介绍了Maven的依赖管理,包括依赖配置、依赖范围(如compile、test、provided、runtime、system)、传递性依赖、依赖冲突调解、排除依赖、可选依赖和归类依赖的实践。通过实例展示了如何在pom.xml中排除和引入特定版本的依赖,以优化项目的构建过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Maven三大功能:依赖管理、项目构建、项目知识管理;需要上项目最重要的功能是首先能用Maven正确添加需要的JAR(依赖管理)

classifier:用来帮助定义构建输出的一些附属构建;不能直接定义项目的classifier,因附属构建不是项目直接默认生成的,而是由附加的插件帮助生成。

pom.xml基础配置:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <!-- modelVersion 指定POM的版本,对于maven2及maven3来说,它只能是4.0.0 -->  
  <modelVersion>4.0.0</modelVersion>
  <!-- groupId、artifactId、version、package和classifier可唯一确定Maven坐标; -->
  <!-- groupId 项目组的ID,一般是com.公司组织名.项目名 -->
  <groupId>com.chensan.app</groupId>
  <!-- artifactId 该项目在项目组中的ID -->
  <artifactId>app-sample</artifactId>
  <!-- version 是项目的版本号,用于维护项目的升级和发布;SNAPSHOT意为快照,说明该项目还处于开发中,是不稳定的版本 -->
  <version>0.0.1-SNAPSHOT</version>
  <!-- Maven项目的打包方式, 有jar、war、pom等方式, 默认打包方式jar -->
  <packaging>jar</packaging>
  <!-- name 一般没有实际的用处, 只是用于标识该项目, Maven产生的文档用 -->
  <name>app-sample</name>
  <!-- 项目主页的URL, Maven产生的文档用 -->
  <url>http://maven.apache.org</url>
  
  <!-- 依赖管理在下面依次会引入 -->
</project>

1. 依赖的配置

依赖可以包含的元素:
groupId,artifactId和version:依赖的基本坐标,对于任何一个依赖来说,基本坐标是最重要的,Maven根据坐标才能找到需要的依赖。
根元素project下的dependencies可以包含一个或者多个dependency元素,以声明一个或者多个依赖。
type: 依赖的类型,对应于项目坐标定义的packaging。大部分情况下,该元素不必声明,其默认值是jar
scope: 依赖的范围,下面会进行详解
optional: 标记依赖是否可选
exclusions: 用来排除传递性依赖,下面会进行详解

2. 依赖范围

Maven在编译、测试、运行时分别要使用一套classpath,依赖范围就是用来控制依赖与依赖与这三种classpath(编译classpath、测试classpath、运行classpath)的关系。
Maven有四种依赖范围:
1) compile:编译依赖范围,如果没有指定依赖范围,则默认使用此依赖范围; 对于编译、测试、运行三种 classpath 都有效,即在编译、测试和运行的时候都使用该依赖;
2) test:测试依赖范围; 在编译主代码和运行项目时无法使用此类依赖。典型的是JUnit,它只用于编译测试代码和运行测试代码的时候才需要;
3) provided:已提供依赖范围,对于编译和测试classpath有效, 但在运行时无效;
4) runtime:运行时依赖范围,对于测试和运行classpath有效,但是在编译主代码时无效;
5) system:系统依赖范围, 该依赖与三种classpath的关系和provided依赖范围完全一致。但是使用system范围的依赖时必须通过systemPath元素显示地指定依赖文件的路径; 由于此类依赖不是通过Maven仓库解析的, 而且往往与本机系统绑定, 可能造成构建的不可 移植所以可能会造成建构的不可移植,须谨慎使用。


3.传递性依赖

参考自:曙光城邦

在Maven官网看到的关系图又跟这有出入,官网中provided+provided=>无 
http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Scope

另外有一篇博文对Maven的传递性依赖的理解有帮助Sean部落阁,只是我看不太懂,不过提供的思路,就是按依赖范围,在什么时间点开始产生依赖和销毁依赖(依赖存在的时间段),用来理解传递依赖肯定是没问题。希望对大家有帮助^-^
A->B(compile)     第一直接依赖关系: a依赖b
B->C(compile)     第二直接依赖关系: b依赖c
则A对C是传递性依赖。
当在A中配置
<dependency>  
  <groupId>com.B</groupId>  
  <artifactId>B</artifactId>  
  <version>1.0</version>  
</dependency>
则会自动导入c包
实例: 当前项目pom.xml为第一直接关系
<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.12</version>
  <scope>test</scope>
</dependency>
Ctrl+鼠标左键点击,进入junit:4.12.pom中,里面有引用hamcrest-core-1.3.jar,此为第二直接关系:
<dependencies>
  <dependency>
	<groupId>org.hamcrest</groupId>
	<artifactId>hamcrest-core</artifactId>
	<version>1.3</version>
  </dependency>
</dependencies>
于是项目中也会传递依赖引入hamcrest-core-1.3.jar


引入jar包依赖可直接在pom.xml中编码写,也可在不同视图中添加配置

4.依赖冲突调解

Maven依赖调解的第一原则,路径最短者优先。
A->B->C->X(1.0)
A->D->X(2.0)
由于只能引入一个版本的包,此时Maven按照最短路径选择导入x(2.0)

Maven依赖调解的第二原则:路径长度一致,第一声明者优先。
多个声明的路径一样长,则只解析最前面的那个声明。
A->B->X(1.0)
A->D->X(2.0)
路径长度一致,优先选择第一个,此时导入x(1.0)

5.排除依赖

A->B->C(1.0)
此时在A项目中,不想使用C(1.0),而使用C(2.0)
则需要使用exclusion排除B对C(1.0)的依赖。并在A中引入C(2.0)。
或者说在A中不想引用C的jar包。 
pom.xml中配置
<!--排除B对C的依赖-->
<dependency>  
  <groupId>B</groupId>  
  <artifactId>B</artifactId>  
  <version>0.1</version>  
  <exclusions>
    <exclusion>
 <groupId>C</groupId>  
 <artifactId>C</artifactId><!--无需指定要排除项目的版本号-->
    </exclusion>
  </exclusions>
</dependency> 
<!---在A中引入C(2.0)-->
<dependency>  
  <groupId>C</groupId>  
  <artifactId>C</artifactId>  
  <version>2.0</version>  
</dependency>

实例:还是以引入junit-4.12.jar为例,但是不希望引入hamcrest-core-1.3.jar,而是换为hamcrest-core-1.2.jar(没谁正常适配版本不用,去换低版本的,只是测试下效果,别喷啊);

<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.12</version>
  <scope>runtime</scope>
  <exclusions>
	<exclusion>
	  <groupId>org.hamcrest</groupId>  
	  <artifactId>hamcrest-core</artifactId><!--无需指定要排除项目的版本号version-->
	</exclusion>
  </exclusions>
</dependency>

<dependency>
  <groupId>org.hamcrest</groupId>  
  <artifactId>hamcrest-core</artifactId>  
  <version>1.2</version>
</dependency>

exclusion排除了对hamcrest-core-1.3.jar的传递依赖,则项目不会导入hamcrest-core的jar包;后面dependency可引用该jar包其它版本;


已成功将hamcrest-core-1.3.jar换成1.2版本;

6.可选依赖

有时候我们不想让依赖传递,那么可配置该依赖为可选依赖,将元素optional设置为true即可。
<project>
  ...
  <dependencies>
    <dependency>
      <groupId>sample.ProjectA</groupId>
      <artifactId>Project-A</artifactId>
      <version>1.0</version>
      <optional>true</optional>
    </dependency>
  </dependencies>
</project>

7.归类依赖

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-core</artifactId>
  <version>4.3.4.RELEASE</version>
</dependency>

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-beans</artifactId>
  <version>4.3.4.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>4.3.4.RELEASE</version>
</dependency>
  
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-orm</artifactId>
  <version>4.3.4.RELEASE</version>
</dependency>
  
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aop</artifactId>
  <version>4.3.4.RELEASE</version>
</dependency>
如上 引入spring的一系列jar包,然而后期如果修改jar包版本则管理起来不方便,这里就可以用到归类依赖。

如博文最上面Spring的JAR为同一版本,为方便后期修改和管理,增加了个自定义的property,以后修改只需要修改property里的版本号即可;

<project>
  ...
  <properties>
    <springframework.version>4.3.4.RELEASE</springframework.version>
  </properties>
  
  <!-- 它们自动从项目定义的仓库(本地仓库、中央仓库、远程仓库)中下载项目配置的依赖jar包。-->
  <dependencies>
    ...
	<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>${springframework.version}</version>
    </dependency>
    
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>${springframework.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${springframework.version}</version>
    </dependency>
      
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-orm</artifactId>
      <version>${springframework.version}</version>
    </dependency>
      
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>${springframework.version}</version>
    </dependency>
  </dependencies>
</project>

8.优化依赖

暂且先不讲了
依赖会包含基本的groupId, artifactId,version等元素,根元素project下的dependencies可以包含一个或者多个dependency元素,以声明一个或者多个依赖。
依赖列表:cmd进入工程根目录,执行 mvn dependency:list 会列出项目依赖的列表

这里的spring jar包版本,在Overview视图的Properties中有定义,这里看到的只是变量的引用。具体情况见7.归类依赖。
依赖关系:cmd进入工程根目录,执行 mvn dependency:tree 会列出依赖关系树及各依赖关系
maven eclipse插件已经实现,有图形化显示,在pom.xml的dependency hierarchy页

分析依赖关系 mvn dependency:analyze 查找出在编译和测试中未使用但显示声明的依赖

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值