Maven(二)

Mvane的依赖范围

Maven 的依赖范围(Dependency Scope)用于精确控制依赖项在项目构建生命周期中的使用阶段和传递性,是避免依赖冲突和优化构建的关键配置。

Scope 是否参与编译 是否参与测试 是否打包 是否传递 典型应用场景
compile 核心依赖(如 Spring Core、Lombok)
provided 容器/运行时提供的依赖(如 Servlet API)
runtime 运行时需但编译不需的依赖(如 JDBC 驱动)
test 测试专用库(如 JUnit、Mockito)
system 本地系统路径的依赖(不推荐使用)
import - - - - 仅用于 <dependencyManagement>

其实也就是我们在引入依赖的时候可选的<scope>标签,在这里面填写依赖的范围如下:

复制代码
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
<!-- 就是这个--!>
    <scope>provided</scope>
</dependency>

其他的都还好理解,一般来说我们也不会去填写,高级的特性也就是最后一个improt这个范围,import 是 Maven 依赖范围中最特殊 的一种,它仅用于 <dependencyManagement> 部分,专门用来继承第三方项目的依赖管理配置(如 Spring Boot 或 Dubbo 的 POM 文件)。

特性 说明
唯一用途 仅在 <dependencyManagement> 中生效,用于导入第三方 POM 的依赖管理配置
非传统依赖范围 不参与编译、测试、打包,​仅做依赖版本管理
依赖传递性 无传递性(不会引入实际依赖)
典型应用场景 统一管理多模块项目或生态系统的依赖版本(如 Spring Cloud 版本对齐)

这个有什么作用呢?一般就是用来进行版本管理的,这个其实和继承有点类似,但是区别也是很明显的,因为导入只会导入<dependencyManagement> 中的内容,而且导入后还必须声明依赖不然这个依赖也不回被导入,就比如Bpom有个a依赖版本是1,Apom导入了Bpom,如果不在<dependencies>(Apom中<dependencyManagement>外的<dependencies>才行)中声明a依赖也是没有用的不会真正导入。如果声明了依赖没声明版本就会默认使用Bpom中的版本,如果声明了版本就会使用A的。

特性 继承 (<parent>)​ 导入 (<scope>import)​
语法 在 POM 中声明 <parent> <dependencyManagement> 中声明 import
继承内容 父 POM 的所有配置(依赖、插件、属性等) 仅合并目标 POM 的 <dependencyManagement>
多继承支持 ❌ 只能单继承 ✅ 可导入多个 BOM
依赖传递 父 POM 的普通 <dependencies> 会传递 仅版本管理,需显式声明依赖
插件配置 继承父 POM 的 <build> 配置 ❌ 不继承插件
适用场景 统一项目结构、共享插件/资源 集中管理依赖版本(如 Spring Boot BOM)
复制代码
<project>
    <dependencyManagement>
        <dependencies>
            <!-- 导入 B 的 dependencyManagement -->
            <dependency>
                <groupId>com.example</groupId>
                <artifactId>B</artifactId>
                <version>1.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
#也可以在这里声明版本,这个声明的上下没关系,只要在Apom的dependencyManagement中声明了就不会使用Bpom的版本,当然还是要在外面声明依赖,不然依赖还是不会被引入
            <dependency>
            <groupId>com.example</groupId>
            <artifactId>a</artifactId>
            <version>1</version>
        </dependency>
        </dependencies>
    </dependencyManagement>

    <!-- 必须显式声明依赖才会引入 -->
    <dependencies>
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>a</artifactId>
            <!-- 版本从 B 继承 -->
        </dependency>
    </dependencies>
</project>

所以从这些看来,这个<dependencyManagement>标签只是用来统一管理版本的,其他的作用几乎没有用了,要注意的是<dependencyManagement>中定义的依赖的范围、排除、包含什么的标签也是会被导入到Apom的,反正记住只会导入<dependencyManagement>标签中的东西就对了。

Maven的依赖传递

我们上一篇已经说过了A依赖B依赖C这个C是怎么导入的,现在我们需要结合今天的依赖范围来重新认识一下,也就是不同的依赖范围会决定会不会引入C依赖,就比如B依赖的C使用的是provided范围,那么B是不会报错的,但是A使用B的时候如果用到了C那么就会报错,因为C并没有被传递进来。但是一般情况下大家使用的也是默认的依赖范围compile。

还有个最短路径优先的问题,在上面这个图中C 的 1.0 版本会被选中(路径更短),那如果两个路径一样长那么就会出现依赖冲突了,需要我们手动解决了,我们可以显示声明,也可以使用importPOM文件进行统一管理版本。

复制代码
#查看依赖树形结构
mvn dependency:tree

#分析依赖冲突
mvn dependency:tree -Dverbose

我们可以使用上面的命令来查看依赖的树形结构,以及通过命令来查看依赖的冲突。就像下面这样可以查看依赖的树形结构以及每个依赖的范围是怎么样的。分析依赖冲突的这边就不演示了,相比前者就是信息更加充分。

总结

本篇主要讲了Maven的依赖范围和传递关系。

相关推荐
爱读源码的大都督2 分钟前
挑战一下,用Java手写Transformer,先手写QKV,能成功吗?
java·后端·程序员
华仔啊4 分钟前
面试官灵魂拷问:count(1)、count(*)、count(列)到底差在哪?MySQL 性能翻车现场
java·后端
用户0332126663677 分钟前
在Word 中插入页眉页脚:实用 Java 指南
java
奔跑吧邓邓子8 分钟前
【Java实战㊱】Spring Boot邂逅Redis:缓存加速的奇妙之旅
java·spring boot·redis·缓存·实战
杨杨杨大侠10 分钟前
Atlas-Event:高性能事件处理与监控系统
java·github·eventbus
杨杨杨大侠13 分钟前
Atlas Event:解锁事件驱动的潜能
java·github·eventbus
ForteScarlet15 分钟前
Kotlin 2.2.20 现已发布!下个版本的特性抢先看!
android·开发语言·kotlin·jetbrains
失散1317 分钟前
分布式专题——4 大厂生产级Redis高并发分布式锁实战
java·redis·分布式·缓存·架构
MacroZheng20 分钟前
堪称一站式管理平台,同时支持Linux、MySQL、Redis、MongoDB可视化管理!
java·linux·后端
anlogic24 分钟前
Java基础 9.10
java·开发语言·算法