Maven - 依赖的生命周期详解

作者:唐叔在学习
专栏:唐叔的Java实践
标签:Maven依赖管理、Java项目构建、依赖传递性、Spring Boot依赖、Maven最佳实践、项目构建工具、依赖冲突解决、POM文件详解

文章目录

    • 一、开篇
    • 二、Maven依赖生命周期
      • 2.1 依赖声明阶段:POM文件的艺术
      • 2.2 依赖解析阶段:Maven仓库的寻宝游戏
      • 2.3 依赖传递性:你的依赖的依赖的依赖...
      • 2.4 依赖范围(Scope):不同阶段的不同需求
      • 2.5 依赖调解:当冲突不可避免时...
    • 三、高级技巧
      • 3.1 BOM管理:统一版本的神器
      • 3.2 可选依赖(optional)与排除依赖(exclusion)
      • 3.3 依赖分类标签
    • 四、总结

一、开篇

各位CSDN的小伙伴们好,我是你们的老朋友唐叔!今天咱们来聊聊Java开发中那个让人又爱又恨的家伙——Maven。作为Apache旗下的顶级项目,Maven早已成为Java生态中不可或缺的构建工具。据最新统计,超过78%的Java项目都在使用Maven进行依赖管理!

但很多小伙伴对Maven的依赖机制一知半解,经常遇到诸如:

  • “明明加了依赖,为什么ClassNotFound?”
  • “这个jar包哪来的?我的pom里没声明啊!”
  • “为什么本地运行正常,打包就报错?”

今天唐叔就带大家彻底搞懂Maven依赖的生命周期,让你从此告别依赖地狱!

二、Maven依赖生命周期

2.1 依赖声明阶段:POM文件的艺术

在Maven的世界里,一切依赖都始于pom.xml。这个看似简单的XML文件,实则暗藏玄机。来看个Spring Boot项目的经典依赖声明:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.7.0</version><scope>compile</scope>
</dependency>

这里包含四个关键要素:

  1. groupId:组织标识(如org.springframework.boot)
  2. artifactId:项目标识(如spring-boot-starter-web)
  3. version:版本号(强烈建议使用明确版本)
  4. scope:依赖范围(compile/runtime/test等)

唐叔小贴士:现在流行用Spring Boot的starter系列,它们其实是精心设计的"依赖包套餐",比如spring-boot-starter-web就自动包含了Spring MVC、Tomcat等常用组件。

2.2 依赖解析阶段:Maven仓库的寻宝游戏

当你执行mvn compile时,Maven会开启一场跨越本地仓库、中央仓库、私服的寻宝之旅:

  1. 本地仓库:默认在~/.m2/repository,优先查找
  2. 中央仓库:repo.maven.apache.org,Maven官方维护
  3. 私服仓库:公司内部搭建的Nexus/Artifactory
  4. 镜像仓库:阿里云等提供的国内镜像(推荐配置)
未找到
项目POM
本地仓库
远程仓库
中央仓库
私服仓库
镜像仓库

热点SEO技巧:国内开发者强烈建议配置阿里云镜像,速度提升10倍不止!在settings.xml中加入:

<mirror><id>aliyunmaven</id><mirrorOf>*</mirrorOf><name>阿里云公共仓库</name><url>https://maven.aliyun.com/repository/public</url>
</mirror>

2.3 依赖传递性:你的依赖的依赖的依赖…

这是Maven最强大的特性,也是最容易出问题的点!比如你引入了spring-boot-starter-web,它会自动带来:

  • spring-boot-starter
  • spring-core
  • jackson-databind
  • tomcat-embed-core
  • …(共20+个传递依赖)

唐叔划重点:可以用mvn dependency:tree查看完整的依赖树,这是排查冲突的利器!

2.4 依赖范围(Scope):不同阶段的不同需求

Maven定义了6种依赖范围,掌握它们能显著优化构建:

Scope编译期测试期运行期典型示例
compilespring-core
provided×servlet-api
runtime×JDBC驱动
test××JUnit
system×本地系统路径的JAR
import---dependencyManagement

实战场景:开发Spring Boot应用时,打包成可执行JAR不需要包含Tomcat(因为内嵌了),但如果是WAR包部署到外部Tomcat,就需要把Tomcat依赖设为provided。

2.5 依赖调解:当冲突不可避免时…

当多个传递依赖引入不同版本时,Maven有两个调解原则:

  1. 最短路径优先:A→B→C→D(1.0) vs A→E→D(2.0) → 选择D(2.0)
  2. 先声明优先:在pom中先声明的依赖优先

冲突解决方案

<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.13.1</version><exclusions><exclusion><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-annotations</artifactId></exclusion></exclusions>
</dependency>

三、高级技巧

3.1 BOM管理:统一版本的神器

Spring Cloud等大型项目都采用BOM(Bill of Materials)管理依赖版本:

<dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>2021.0.3</version><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement>

3.2 可选依赖(optional)与排除依赖(exclusion)

  • optional=true:表示该依赖不会被传递
  • exclusion:主动排除特定的传递依赖

3.3 依赖分类标签

<dependencies><!-- 核心功能 --><dependency>...</dependency><!-- 数据库相关 --><dependency>...</dependency><!-- 测试相关 --><dependency>...</dependency>
</dependencies>

四、总结

  1. 明确声明:尽量指定版本号,避免使用LATEST
  2. 善用dependencyManagement:多模块项目统一管理版本
  3. 定期检查依赖:mvn dependency:analyze发现无用依赖
  4. 理解传递性:dependency:tree是最好用的调试工具
  5. 合理使用Scope:优化最终打包内容
  6. 拥抱BOM:大型项目版本管理必备

唐叔最后送大家一句话:"好的依赖管理就像好的城市规划,既要四通八达,又要避免拥堵混乱。"希望这篇文章能帮你成为Maven依赖管理的高手!

思考题:你们项目中有没有遇到过奇葩的依赖冲突?是怎么解决的?欢迎在评论区分享你的故事!

觉得有帮助的小伙伴别忘了点赞收藏!点击关注唐叔,每周解锁Java干货!


相关maven文章推荐

✅ Maven - 并行安全无重复打包构建原理揭秘
✅ Maven BOM机制 - Maven复杂依赖关系管理“神器“
✅ IDEA 多线程打包 Maven 模块:让你的构建速度飞起来!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/917439.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/917439.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从零打造大语言模型--处理文本数据

从零打造大语言模型 第 1 章&#xff1a;处理文本数据 章节导读 在把文本投喂进 Transformer 之前&#xff0c;需要两步&#xff1a;① 将字符流切分成离散 Token&#xff1b;② 把 Token 映射成连续向量。 1.1 理解词嵌入&#xff08;Word Embedding&#xff09; 嵌入向量 一…

【Spring】Bean的生命周期,部分源码解释

文章目录Bean 的生命周期执行流程代码演示执行结果源码阅读AbstractAutowireCapableBeanFactorydoCreateBeaninitializeBeanBean 的生命周期 生命周期指的是一个对象从诞生到销毁的整个生命过程&#xff0c;我们把这个过程就叫做一个对象的声明周期 Bean 的声明周期分为以下 …

[spring-cloud: 服务发现]-源码解析

DiscoveryClient DiscoveryClient 接口定义了常见的服务发现操作&#xff0c;如获取服务实例、获取所有服务ID、验证客户端可用性等&#xff0c;通常用于 Eureka 或 Consul 等服务发现框架。 public interface DiscoveryClient extends Ordered {/*** Default order of the dis…

QML 基础语法与对象模型

QML (Qt Meta-Object Language) 是一种声明式语言&#xff0c;专为创建流畅的用户界面和应用程序逻辑而设计。作为 Qt 框架的一部分&#xff0c;QML 提供了简洁、直观的语法来描述 UI 组件及其交互方式。本文将深入解析 QML 的基础语法和对象模型。 一、QML 基础语法 1. 基本对…

HTTPS的概念和工作过程

一.HTTPS是什么HTTPS也是一个应用层协议&#xff0c;是在HTTP协议的基础上引入了一个加密层&#xff08;SSL&#xff09;HTTP协议内容都是按照文本的方式明文传输的&#xff0c;这就导致传输过程中可能出现被篡改的情况最著名的就是十多年前网络刚发展的时期&#xff0c;出现“…

Unity —— Android 应用构建与发布​

文章目录1 ​Gradle模板​​&#xff1a;了解Gradle模板的作用及使用方法&#xff0c;以增强对构建流程的控制。​2 ​Gradle模板变量​​&#xff1a;参考文档——自定义Gradle模板文件中可用的变量列表。2.1 修改Unity应用的Gradle工程文件2.1.1 通过Gradle模板文件2.1.2 导出…

【iOS】strong和copy工作流程探寻、OC属性关键字复习

文章目录前言strong和copy的区别为什么要用copy&#xff1f;什么时候用什么修饰&#xff1f;strong&#xff08;ARC自动管理&#xff09;strong修饰变量的底层流程图底层代码核心实现小结copy底层流程图对比与strong的关键不同之处内部调用关系&#xff08;伪代码&#xff09;小…

程序代码篇---多循环串口程序切换

上位机版&#xff08;Python&#xff09;要实现根据串口接收结果高效切换四个 while 循环函数&#xff0c;我们可以采用状态机模式&#xff0c;配合非阻塞串口读取来设计程序结构。这种方式可以实现快速切换&#xff0c;避免不必要的资源消耗。下面是一个高效的实现方案&#x…

rk3568上,实现ota,计算hash,验证签名,判断激活分区,并通过dd命令,写入对应AB分区

通过自定义升级程序&#xff0c;更直观的理解ota升级原理。 一、模拟计算hash&#xff0c;验证签名&#xff0c;判断激活分区&#xff0c;并通过dd命令&#xff0c;写入对应分区 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <u…

数据分析—numpy库

numpy库NumPy 库全面指南NumPy (Numerical Python) 是 Python 科学计算的基础库&#xff0c;提供了高性能的多维数组对象和工具。以下是 NumPy 的核心功能和使用方法。一、安装与基础1. 安装 NumPypip install numpy2. 导入 NumPyimport numpy as np # 标准导入方式二、数组创建…

Vue3 setup、ref和reactive函数

一、setup函数1.理解&#xff1a;Vue3.0中一个新的配置项&#xff0c;值为一个函数。2.setup是所有Composition API(组合API)的“表演舞台”。3.组件中用到的&#xff1a;数据、方法等等&#xff0c;均要配置在setup中。4.setup函数的两种返回值&#xff1a;(1).若返回一个对象…

python中appium 的NoSuchElementException错误 原因以及解决办法

错误收集D:\Program\Util\python.exe "D:/Program/myUtil/PyCharm 2024.3.5/plugins/python-ce/helpers/pycharm/_jb_pytest_runner.py" --target demo.py::TestAppium Testing started at 15:57 ... Launching pytest with arguments demo.py::TestAppium --no-hea…

mybatis-plus从入门到入土(四):持久层接口之BaseMapper和选装件

大家好&#xff0c;今天继续更新MybatisPlus从入门到入土系列&#xff0c;上一次的持久层接口还没讲完&#xff0c;只讲了IService接口&#xff0c;今天我们继续来讲一下。 BaseMapper BaseMapper中的方法也比较简单&#xff0c;都是增删改查的基础API&#xff0c;不知道大家还…

数组和指针的关系

在 C 语言中&#xff0c;​指针和数组有着非常紧密的联系&#xff0c;但它们本质上是 ​不同的概念。理解它们的关系是掌握 C 语言内存操作的关键。下面我会从多个角度帮你梳理 ​指针和数组的直接联系&#xff0c;并解释它们的异同点。1. 数组和指针的本质区别​概念本质存储方…

AI大模型探索之路-实战篇:智能化IT领域搜索引擎之github网站在线搜索

系列篇章💥 No. 文章 1 AI大模型探索之路-实战篇:智能化IT领域搜索引擎的构建与初步实践 2 AI大模型探索之路-实战篇:智能化IT领域搜索引擎之GLM-4大模型技术的实践探索 3 AI大模型探索之路-实战篇:智能化IT领域搜索引擎之知乎网站数据获取(初步实践) 4 AI大模型探索之路…

从0到1学PHP(十二):PHP 框架入门与项目实战

目录一、主流 PHP 框架介绍1.1 Laravel1.2 ThinkPHP1.3 Yii1.4 框架的优势二、框架基本使用&#xff08;以 Laravel 为例&#xff09;2.1 框架的安装与配置2.2 路由定义、控制器创建、视图渲染2.3 数据库操作&#xff08;ORM 的使用&#xff09;三、小型项目实战3.1 项目需求分…

MPLS LSP

一、概述上一章我们已经介绍过,LSP是MPLS报文在MPLS网络中转发时经过的路径,可以看作是由报文传输方向节点为对应FEC分配的MPLS入标签组成的,因为每台设备上为每个FEC分配的入标签是唯一 的&#xff0c;并与由下游节点为本地节点上该FEC分配的出标签建立映射关系&#xff0c; 所…

图像、视频、音频多模态大模型中长上下文token压缩方法综述

多模态大模型MLLMs 能够处理高分辨率图像、长视频序列和冗长音频输入等复杂上下文&#xff0c;但自注意力机制的二次复杂度使得大量输入 token 带来了巨大的计算和内存需求。 如下图&#xff0c;上&#xff1a;图像、视频和音频数据类型可以在其表示维度上进行扩展&#xff0c;…

Spring MVC 九大组件源码深度剖析(一):MultipartResolver - 文件上传的幕后指挥官

文章目录一、为什么从 MultipartResolver 开始&#xff1f;二、核心接口&#xff1a;定义文件上传的契约三、实现解析&#xff1a;两种策略的源码较量1. StandardServletMultipartResolver&#xff08;Servlet 3.0 首选&#xff09;2. CommonsMultipartResolver&#xff08;兼容…

stm32是如何实现电源控制的?

STM32的电源控制主要通过内置的电源管理模块&#xff08;PWR&#xff09;实现&#xff0c;涵盖电压调节、功耗模式切换和电源监控等功能。以下是其核心机制及实现方式&#xff1a;​​1. 电源架构与供电区域​​STM32的电源系统分为多个供电区域&#xff0c;各司其职&#xff1…