前言
Maven中三种不同的类路径
classpath范围 | 理解为 |
---|---|
编译类路径 | 只在main目录下源代码起作用 |
测试类路径 | 只在test目录下起作用 |
运行时类路径 | 在运行的时候起作用,可以理解为会打包到target目录下 |
依赖范围 | main编译类路径 | test测试类路径 | target运行时类路径 | 举例 |
---|---|---|---|---|
compile | Y | Y | Y | Log4j |
provided | Y | Y | Servlet | |
runtime | Y | Y | mysql | |
test | Y | junit |
一、依赖传递
概念:某个项目依赖了另一个项目,另一个项目中jar包会不会传递到这个项目中来。
1. 项目A依赖junit,依赖范围是test,项目B依赖项目A,问: 项目B对junit是否有依赖? 不支持
2. 项目A依赖junit,依赖范围是compile,项目B依赖项目A,问: 项目B对junit是否有依赖? 支持
3. 项目A依赖junit,依赖范围是provided,项目B依赖项目A,问: 项目B对junit是否有依赖? 不支持
4. 项目A依赖junit,依赖范围是runtime,项目B依赖项目A,问: 项目B对junit是否有依赖?支持
A模块 (默认-compile-传递)
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
B模块(依赖A模块)
<!-- 依赖A -->
<dependencies>
<dependency>
<groupId>com.hntou</groupId>
<artifactId>RelyOnPassA</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
A模块 (provided-不传递)
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>provided</scope>
</dependency>
</dependencies>
A模块 (test-不传递)
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
A模块 (runtime-传递)
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>runtime</scope>
</dependency>
</dependencies>
1.有哪几种依赖范围?
compile默认
provided
test
runtime
2.哪几种依赖范围会产生依赖传递?
compile (默认)
runtime
结论:在运行时类路径中起作用的依赖范围会产生依赖传递
二、依赖可选
前提是会产生依赖传递的两种情况
什么是可选依赖
1.A项目依赖了junit
2.B项目依赖了A项目
3.根据依赖传递特性,默认情况下B项目会依赖junit
4.我们可以在A项目通过可选依赖,让B项目不能依赖junit
配置方式
在A项目的依赖配置中,通过optional子标签进行配置。它有两个取值:
true:是可选依赖,不进行依赖传递
false:默认值,进行依赖传递。
三、依赖排除
1.A项目依赖了junit
2.B项目依赖了A项目
3.根据依赖传递特性,默认情况下B项目会依赖junit
4.我们可以在B项目通过排除依赖,配置B项目不依赖junit
配置步骤
通过在B项目中配置 exclusions标签进行配置
1. 在依赖A项目下的version标签下编写exclusions
2. exclusions中每个exclusion是一个要排除的jar包
3. 只需指定groupId和artifactId就可以了,不用指定version版本
A项目
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>compile</scope>
</dependency>
</dependencies>
B项目
<!-- 依赖A -->
<dependencies>
<dependency>
<groupId>com.hntou</groupId>
<artifactId>RelyOnPassA</artifactId>
<version>1.0-SNAPSHOT</version>
<exclusions>
<!-- 不接收A项目的依赖 -->
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
什么是依赖可选?
由A项目来决定给不给,通过标签<optional>来配置
什么是依赖排除?
由B项目来决定要不要,通过标签<exclusion>来配置
四、依赖冲突
Maven中,项目导入了同一个依赖的不同版本,maven为了解决依赖冲突就会选择其中一个版本,所以配合依赖排除使用。
4.1 情况1:两个直接依赖
一个项目中同时配置了2份junit4.12和junit4.11不同的版本,项目最终会使用哪个junit的版本?
两个直接依赖,取下面的
4.2 情况2:一个直接依赖一个间接依赖
一个直接一个间接,取直接
4.3 情况3:两个间接依赖
spring-core包到底使用哪个?
1.spring-aop 5.2.0间接依赖了spring-core和spring-beans
2.spring-tx 4.2.8间接依赖了spring-core和spring-beans
两个间接依赖取上面的为准
<!-- spring-aop包括spring-core和spring-beans 传递依赖(间接) -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<!-- 两个间接取上面的,最终会core和beans是5.2.0的版本 -->
<!-- spring-tx包括 spring-core和spring-breans 传递依赖(间接) -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.4.RELEASE</version>
</dependency>
依赖冲突的三种情况 | 依赖如何处理的 |
---|---|
两个直接依赖 | 以下面配置的为准 |
一个直接依赖一个间接依赖 | 以直接为准 |
两个间接依赖 | 以上面配置的为准 |
可以通过改变位置或者是依赖排除选择自己想要的版本