【Maven从入门到实战教程】第六章 Maven依赖传递详解 不念不忘少年蓝@ 2024-04-28 13:17 84阅读 0赞 ### 依赖传递 ### 大家要理解一个问题:Maven仓库中的所有jar,其实本质上都是一个Java项目,只是打成jar包放到Maven仓库中而已,既然是Java项目,那么这个项目可能也会用到一些第三方的jar包。 当我们引入某些jar包的时候,会把这些jar包依赖的jar包同样引入进来,这就是依赖传递。 ![watermark_type_d3F5LXplbmhlaQ_shadow_50_text_Q1NETiBA5oiR5piv5rOi5ZOp5Liq5rOi_size_16_color_FFFFFF_t_70_g_se_x_16][] 例如有个Commons-logging项目,项目Spring-core依赖Commons-logging,而项目user-service依赖Spring-core。那么我们可以说 user-service也依赖Commons-logging。也就是说,依赖的关系为:user-service—>Spring-core—>Commons-logging 当我们执行项目user-service时,会自动把Spring-core、Commons-logging都下载导入到user-service项目的jar包文件夹中,这就是依赖的传递性。 **dependency完整结构:** <dependencies> <dependency> <groupId>组织/父项目名称</groupId> <artifactId>项目名称</artifactId> <version>项目版本号</version> <type>依赖的类型,对应项目的packaging,默认是jar</type> <scope>依赖范围</scope> <systemPath>配合 scope=system 时使用</systemPath> <optional>标记是否为可选依赖</optional> <exclusions> <!-- 用来排除传递性依赖 --> <exclusion> <groupId>组织/父项目名称</groupId> <artifactId>项目名称</artifactId> </exclusion> </exclusions> </dependency> </dependencies> 通过设置<optional>true</optional>,表示该依赖是可选的,不会被依赖传递。 **举例验证:** 引入依赖spring-core。 <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.3.18.RELEASE</version> </dependency> **结果如下:** ![watermark_type_d3F5LXplbmhlaQ_shadow_50_text_Q1NETiBA5oiR5piv5rOi5ZOp5Liq5rOi_size_10_color_FFFFFF_t_70_g_se_x_16][] 仔细观察,还发现此时还多了commons-logging:commons-logging:1.2,这就涉及到了“依赖”。 当A jar包需要用到B jar包中的类时,我们就说A对B有依赖。当前工程会到本地仓库中根据坐标查找它所依赖的jar包。 我们通过Maven仓库可以发现,spring-core编译的时候依赖了5个jar,但是最终依赖传递进来的只有一个,原因在于配置了optinal标签。 注意:optional标签只能在自己的项目中设置不向下传递(如果我们把项目打成jar包,我们项目的中的某些依赖不向下传递),如果不想使用要别人项目传递进来的依赖,可以使用依赖传递的排除。 ![watermark_type_d3F5LXplbmhlaQ_shadow_50_text_Q1NETiBA5oiR5piv5rOi5ZOp5Liq5rOi_size_16_color_FFFFFF_t_70_g_se_x_16 1][] ### 依赖传递的排除 ### 有时候为了确保程序正确,可以将有可能重复的间接依赖排除。 依赖传递的排除的排除分为两种: 1、通过配置文件排除依赖。 2、Maven自动排除重复依赖。 **例如:C -> B -> A,假如现在不想执行C时把A下载进来,那么我们可以用<exclusions>标签** <dependencies> <dependency> <groupId>B</groupId> <artifactId>B</artifactId> <version>0.0.1</version> <exclusions> <exclusion> <!--被排除的依赖包坐标--> <groupId>A</groupId> <artifactId>A</artifactId> </exclusion> </exclusions> </dependency> </dependencies> 我们一般情况下,不要自己去写依赖排除,除非某些特殊情况。 假如:junit依赖的hamcrest-core:1.3有版本问题,我们不想要junit依赖传递进来的hamcrest-core:1.3,那么我们就可以通过exclusion排除掉。 <!-- 引入junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> <exclusions> <exclusion> <groupId>org.hamcrest</groupId> <artifactId>hamcrest-core</artifactId> </exclusion> </exclusions> </dependency> **注意:要跟原来引出依赖的原包处于同一个`<dependency></dependency>`范围。** 依赖排除hamcrest-core之后,junit肯定就出现了问题,那么我们需要找一个没有版本问题的hamcrest-core再引入进来即可。 <!-- 引入hamcrest-core --> <dependency> <groupId>org.hamcrest</groupId> <artifactId>hamcrest-core</artifactId> <version>2.2</version> </dependency> **依赖排除的场景:** 1、项目A依赖项目B,但当项目A不是完全依赖项目B的时候,即项目A只用到了项目B的一部分功能,而正巧项目B这部分功能的实现,并不需要依赖于项目C,这个时候,项目A就应该排除对项目C的依赖。 2、版本不匹配:依赖传递进来的jar包与实际用到的jar有版本不匹配问题,造成项目运行异常。 3、封装公共模块:使用到某个jar中的API,如果此jar中有不需要的传递依赖,可以通过排除依赖传递。 ### 依赖冲突与解决 ### 依赖冲突:一个项目A,通过不同依赖传递路径依赖于X,若在不同路径下传递过来的X版本不同,那么A应该导入哪个版本的X包呢? 由于依赖的内容存在多个版本,如果出现某一个POM依赖多个版本时,则称之为依赖冲突。 依赖冲突遵循两个原则: 1、短路优先(依赖的内容,传递次数越小越优先)。 2、先声明则优先(在POM.xml中,哪个依赖的内容声明dependency靠前,则优先。 **举例验证:** 引入如下依赖: <!-- spring核心包 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.3.18.RELEASE</version> </dependency> <!-- spring beans包 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>4.3.18.RELEASE</version> </dependency> <!-- spring环境包 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.18.RELEASE</version> </dependency> 我们会发现,我们引入了spring-core,但是beans、context以及context里面的aop等都依赖传递了spring-core。那么项目中会引入多个jar吗? 答案是否定的。实际上Maven只引入了一个spring-core。 ![watermark_type_d3F5LXplbmhlaQ_shadow_50_text_Q1NETiBA5oiR5piv5rOi5ZOp5Liq5rOi_size_14_color_FFFFFF_t_70_g_se_x_16][] **冲突解决方案:** 1、如果依赖路径的长度不同,则采取最短路径原则: A—>B—>C—>D—>E—>X(version 0.0.2) A—>F—>X(version 0.0.1) 则A依赖于X(version 0.0.1)。 2、依赖路径长度相同情况下,则采取最先申明原则: A—>E—>X(version 0.0.1) A—>F—>X(version 0.0.2) 则在项目A的<depencies></depencies>中,E、F哪个先声明则A依赖哪条路径的X。 [watermark_type_d3F5LXplbmhlaQ_shadow_50_text_Q1NETiBA5oiR5piv5rOi5ZOp5Liq5rOi_size_16_color_FFFFFF_t_70_g_se_x_16]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/28/a25316f8cee749baa4844954cc9f9f39.png [watermark_type_d3F5LXplbmhlaQ_shadow_50_text_Q1NETiBA5oiR5piv5rOi5ZOp5Liq5rOi_size_10_color_FFFFFF_t_70_g_se_x_16]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/28/ed3c5b1495dc4d049a1d777a47f1d32b.png [watermark_type_d3F5LXplbmhlaQ_shadow_50_text_Q1NETiBA5oiR5piv5rOi5ZOp5Liq5rOi_size_16_color_FFFFFF_t_70_g_se_x_16 1]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/28/e8c7088d8c21421da57d29c9c56dff17.png [watermark_type_d3F5LXplbmhlaQ_shadow_50_text_Q1NETiBA5oiR5piv5rOi5ZOp5Liq5rOi_size_14_color_FFFFFF_t_70_g_se_x_16]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/28/cf12673c2aba42a8bf383b9629c1a480.png
相关 【Spring从入门到实战教程】第六章 Spring 事务管理详解 1、事务概述2、事务属性:传播行为、隔离级别、回滚、只读事务、超时3、事务案例 ゝ一纸荒年。/ 2024年04月28日 13:21/ 0 赞/ 80 阅读
相关 【Mybatis从入门到实战教程】第六章 Mybatis 延迟加载详解 Mybatis 延迟加载:使用association实现延迟加载使用collection实现延迟加载 小鱼儿/ 2024年04月28日 13:20/ 0 赞/ 97 阅读
相关 【Maven从入门到实战教程】第八章 Maven项目拆分、继承、聚合,配套Maven综合案例 一、Maven项目拆分、继承、聚合的深入理解二、Maven综合案例 末蓝、/ 2024年04月28日 13:18/ 0 赞/ 79 阅读
相关 【Maven从入门到实战教程】第四章 在Eclipse和IDEA中使用Maven 一、在eclipse中使用Maven二、在IDEA中使用Maven 落日映苍穹つ/ 2024年04月28日 13:17/ 0 赞/ 85 阅读
相关 【Maven从入门到实战教程】第一章 Maven概念、安装和配置 一、Maven概念:简介、Maven概念模型二、Maven安装与配置:安装、配置、全局settings与用户settings、配置阿里云镜像 我就是我/ 2024年04月28日 13:17/ 0 赞/ 66 阅读
还没有评论,来说两句吧...