一、Maven简介

Maven是一个跨平台的项目管理工具。作为Apache组织的一个颇为成功的开源项目,其主要服务于基于Java平台的项目创建,依赖管理和项目信息管理。

二、Maven的依赖管理

1、依赖配置

基本配置:

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

大部分依赖声明只包含基本坐标

2、依赖范围

Maven在编译主代码的时候需要使用一套classpath,在编译和执行测试的时候会使用另一套classpath,实际运行项目的时候,又会使用一套classpath。

依赖范围就是用来控制依赖与这三种classpath(编译classpath、测试classpath、运行classpath)的关系,Maven有以下几种依赖范围:
  • compile:编译依赖范围。如果没有指定,就会默认使用该依赖范围。使用此依赖范围的Maven依赖,对于编译、测试、运行三种classpath都有效。典型的例子是spring-core,在编译,测试和运行的时候都需要使用该依赖。
  • provided:已提供依赖范围。使用此依赖范围的Maven依赖,对于编译和测试classpath有效,但在运行时无效。典型的例子是servlet-api,编译和测试项目的时候需要该依赖,但在运行项目的时候,由于容器已经提供,就不需要Maven重复地引入一遍。
  • test:测试依赖范围。使用此依赖范围的Maven依赖,只对于测试classpath有效,在编译主代码或者运行项目的使用时将无法使用此类依赖。典型的例子就是JUnit,它只有在编译测试代码及运行测试的时候才需要。
  • runtime:运行时依赖范围。使用此依赖范围的Maven依赖,对于测试和运行classpath有效,但在编译主代码时无效。典型的例子是JDBC驱动实现,项目主代码的编译只需要JDK提供的JDBC接口,只有在执行测试或者运行项目的时候才需要实现上述接口的具体JDBC驱动。
  • system:系统依赖范围。该依赖范围与provided所表示的依赖范围一致,对于编译和测试classpath有效,但在运行时无效。只是使用system范围依赖时必须通过systemPath元素显式地指定依赖文件的路径。由于此类依赖不是通过Maven仓库解析的,而且往往与本机系统绑定,可能造成构建的不可移植,因此应该谨慎使用,systemPath元素可以引用环境变量。

3、传递性依赖

传递性依赖是在maven2中添加的新特征,这个特征的作用就是你不需要考虑你依赖的库文件所需要依赖的库文件,能够将依赖模块的依赖自动的引入。例如我们依赖于spring的库文件,但是spring本身也有依赖,如果没有传递性依赖那就需要我们了解spring项目依赖,自己添加到我们的项目中。有了传递性依赖机制,在使用Spring Framework的时候就不用去考虑它依赖了什么,也不用担心引入多余的依赖。Maven会解析各个直接依赖的POM,将那些必要的间接依赖,以传递性依赖的形式引入到当前的项目中。

例如:项目中用到spring-core,而它又依赖commons-logging,从其构件POM http://repo1.maven.org/maven2/org/springframework/spring-core/4.3.2.RELEASE/spring-core-4.3.2.RELEASE.pom中可以看出

<?xml version="1.0" encoding="UTF-8"?>-<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>4.3.2.RELEASE</version><name>Spring Core</name><description>Spring Core</description><url>https://github.com/spring-projects/spring-framework</url>-<organization><name>Spring IO</name><url>http://projects.spring.io/spring-framework</url></organization>-<licenses>-<license><name>The Apache Software License, Version 2.0</name><url>http://www.apache.org/licenses/LICENSE-2.0.txt</url><distribution>repo</distribution></license></licenses>-<developers>-<developer><id>jhoeller</id><name>Juergen Hoeller</name><email>jhoeller@pivotal.io</email></developer></developers>-<scm><connection>scm:git:git://github.com/spring-projects/spring-framework</connection><developerConnection>scm:git:git://github.com/spring-projects/spring-framework</developerConnection><url>https://github.com/spring-projects/spring-framework</url></scm>-<issueManagement><system>Jira</system><url>https://jira.springsource.org/browse/SPR</url></issueManagement>-<dependencies>-<dependency><groupId>commons-codec</groupId><artifactId>commons-codec</artifactId><version>1.10</version><scope>compile</scope><optional>true</optional></dependency>-<dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version><scope>compile</scope></dependency>-<dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version><scope>compile</scope><optional>true</optional></dependency>-<dependency><groupId>net.sf.jopt-simple</groupId><artifactId>jopt-simple</artifactId><version>5.0.2</version><scope>compile</scope><optional>true</optional></dependency>-<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.9</version><scope>compile</scope><optional>true</optional></dependency></dependencies></project>

可以看出还依赖了其他构建。Maven就是根据次POM文件获得它的依赖的,从而实现传递性依赖。

假设A依赖于B,B依赖于C,我们说A对于B是第一直接依赖,B对C是第二直接依赖,A对于C是传递性依赖。第一直接依赖的范围和第二直接依赖的范围决定了传递性依赖的范围。

最左边一行表示第一直接依赖范围,最上面一行表示第二直接依赖范围,中间的交叉单元格则表示传递性依赖范围。
compile test provided runtime
compile compile --- --- runtime
test test --- --- test
provided provided --- provided provided
runtime runtime --- --- runtime
仔细观察上面表格,我们发现这样的规律:
  • 当第二直接依赖的范围是compile的时候,传递性依赖的范围与第一直接依赖的范围一致;
  • 当第二直接依赖的范围是test的时候,依赖不会得以传递;
  • 当第二直接依赖的范围是provided的时候,只传递第一直接依赖的范围也为provided的依赖,切传递性依赖的范围同样为provided;
  • 当第二直接依赖的范围是runtime的时候,传递性依赖的范围与第一直接依赖的范围一致,但compile例外,此时传递性依赖的范围为runtime。

4、maven对传递性依赖的处理

有些依赖,maven会对其按照下述原理自动处理

1).短路优先:谁离得最近就使用谁的依赖jar包

C到达A为C->B->A

C到达B为C->B

例如:

A中的 commons-io的版本为2.4

B中的commons-io的版本为2.0

C中依赖于B,B依赖于A

则C的junit的包为2.0版本

因为依赖的短路优先

2).如果两条路都是一样长的时候呢?

C到达A为C->A

C到达B为C->B

则看pom文件中依赖的两个工程谁在前面就是用哪个版本

例如:

这里使用的common-io为2.4版本

        <dependency><groupId>org.lonecloud.A</groupId><artifactId>A</artifactId><version>0.0.1-SNAPSHOT</version></dependency><!--C依赖于B但是会将A的依赖传递进来 --><dependency><groupId>org.lonecloud.B</groupId><artifactId>B</artifactId><version>0.0.1-SNAPSHOT</version><!-- 此标签的作用是可以将B的传递依赖关系A不传递给C --><!-- <exclusions> <exclusion> <groupId>org.lonecloud.A</groupId> <artifactId>A</artifactId> </exclusion> </exclusions> --></dependency>

C文件中添加了A和B的依赖项的时候谁最先加载则使用谁的jar包

下面使用的是2.0的版本,也就是B中的jar包

        <dependency><groupId>org.lonecloud.B</groupId><artifactId>B</artifactId><version>0.0.1-SNAPSHOT</version><!-- 此标签的作用是可以将B的传递依赖关系A不传递给C --><!-- <exclusions> <exclusion> <groupId>org.lonecloud.A</groupId> <artifactId>A</artifactId> </exclusion> </exclusions> --></dependency><dependency><groupId>org.lonecloud.A</groupId><artifactId>A</artifactId><version>0.0.1-SNAPSHOT</version></dependency>

三、Maven依赖jar包冲突解决

1、判断jar是否正确的被引用

1)、在项目启动时加上VM参数:-verbose:class

项目启动的时候会把所有加载的jar都打印出来 类似如下的信息:

classpath加载的jar

具体load的类

我们可以通过上面的信息查找对应的jar是否正确的被依赖,具体类加载情况,同时可以看到版本号,确定是否由于依赖冲突造成的jar引用不正确;

2)、 通过maven自带的工具:‍‍mvn dependency:tree

具体后面可以加 -Dverbose 参数 ,详细参数可以去自己搜,这里不详细介绍。

比如分析如下POM

运行: mvn dependency:tree -Dverbose

输出结果:

通过里面的信息可以看到 两个jar都commons-logging存在依赖,但是版本不同。里面的详细信息显示引用了 commons-logging:commons-logging:jar:1.1 去掉了commons-logging:commons-logging:jar:1.0.3 (omitted for duplicate)。

3)、在Myeclipse或者idea或者eclipse中用pom编辑器打开一个pom文件,在Dependency Hierarchy的Tab页中,就可以查看当前pom文件中显示声明的jar包,及这些显示声明的jar中隐式引入的依赖jar包。

这样就可以查看有哪些隐式的依赖jar会导致jar包冲突了。

通过以上方法我们可以看到项目中引用jar版本号;接下来就是如何排除掉我们不想要版本的jar;

2、冲突的解决

1)在pom.xml中引用的包中加入exclusion,排除依赖

<dependency><groupId>com.alibaba</groupId><artifactId>dubbo</artifactId><version>2.5.3</version><exclusions><exclusion><artifactId>spring</artifactId><groupId>org.springframework</groupId></exclusion></exclusions></dependency>

去除全部依赖

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
<exclusions>
<exclusion>
<artifactId>*</artifactId>
<groupId>*</groupId>
</exclusion>
</exclusions>
</dependency>

2)在ide中右击进行处理,处理完后在pom.xml中也会添加exclusion元素




Maven的传递性依赖及其jar包冲突解决相关推荐

  1. Maven构建聚合工程以及jar包冲突解决使用总结

    一.聚合工程 如图所示: SpringCloud_CH3为聚合工程,eurekaclientarticleservice为被聚合工程. 聚合工程为一个maven工程:聚合类的pom.xml文件为: & ...

  2. maven工程servlet实例之jar包冲突解决

    依赖范围 A依赖B,需要在A的pom.xml文件中添加B的坐标,添加坐标时需要指定依赖范围,依赖范围包括: compile:编译范围,指A在编译时依赖B,此范围为默认依赖范围.编译范围的依赖会用在编译 ...

  3. maven导出项目依赖的jar包

    一.导出到默认目录 targed/dependency 从Maven项目中导出项目依赖的jar包:进入工程pom.xml 所在的目录下,执行如下命令: ? 1 mvn dependency:copy- ...

  4. Jar包冲突解决方法 Unknown lifecycle phase mvn Eclipse中执行maven命令

    1.如下图,右击需要执行maven命令的工程,选择"Debug As"或"Run As",再选择"Maven build..." 进行如上操 ...

  5. maven隐式依赖引起的包冲突

    包冲突 使用maven管理项目时可能会遇到包冲突的情况比如:log4j-over-slf4j.jar 和 slf4j-log4j12.jar这两个包同时一起运行时就会有问题. 这种冲突可能是显式依赖导 ...

  6. maven中把依赖的JAR包一起打包(转)

    转自:http://lvjun106.iteye.com/blog/1849803 这里所用到的MAVEN-PLUGIN是MAVNE-ASSEMBLY-PLUGIN 官方网站是:http://mave ...

  7. IntelliJ IDEA Maven jar包冲突解决,快速发现jar包冲突

    IntelliJ IDEA 自带的Diagrams 去查看jar包冲突相当费劲 ~ ,安装个插件即可快速解决该问题 打开Settings,搜索maven helper,并安装 安装完成后,直接打开po ...

  8. Jar包冲突解决方法

    前言 对于Jar包冲突问题,我们开发人员经常都会有碰到,当我们使用一些jar包中的类.方法等,或者有时遇到一些日志系统的问题(参考另一篇文章Jar包冲突导致的日志问题),我们会遇到ClassNotFo ...

  9. jar包冲突解决思路

    工作中,难免会因为各种原因需要对项目jar包进行升级,一升级,就会碰到各种jar包冲突问题,这时候就需要我们能很快定位冲突的位置,以及如何快速调整依赖. 首先,我们通常说的jar包冲突到底是指什么? ...

最新文章

  1. 写高质量的代码,永不言晚!
  2. 程序员,应该掌握的英语词汇
  3. P3935 Calculating 整除分块
  4. 物联网将成为第四次工业革命的基石
  5. leetcode86. 分隔链表
  6. 服务器系统架构的评估,系统架构师:性能评估
  7. android 安装卸载应用提醒_Android程序使用代码的安装和卸载!!!
  8. java复习系列[3] - Java虚拟机
  9. [转]javascript 判断某页面上的表单数据是否改变过
  10. int 最大值_十行代码说清楚:leetcode 队列的最大值
  11. PTA练习4-11 统计素数并求和
  12. 云闪付华为P9指纹_华为云闪付app下载-华为云闪付 安卓版v9.0.11.301-PC6安卓网
  13. 爬虫日记(6):beautifulsoup的基本使用2
  14. 云计算效果如何,Mixpanel现身说法
  15. 为什么说每个软件工程师,都该懂大数据技术?
  16. CornerNet Guassian radius高斯半径的确定-数学公式详解
  17. android nfc扇区加密,uniapp安卓NFC MifareClassic读IC卡加密扇区方法
  18. 从零实施ERP如何成功
  19. 深度学习新手神器,floydhub gpu云主机!
  20. 1602自定义字模方法 CGRAM

热门文章

  1. latex怎么给图片命名_[Latex] Beamer 入门
  2. socket基础知识以及各种使用场景
  3. 【安卓逆向】360加固-脱壳修复
  4. reids3.0安装文档
  5. aizu/aoj-0118-Property Distribution
  6. Hash MSDN MD4 MD5 SHA1 CRC 详细解释
  7. 【ALGO】基础算法(3)
  8. 会计初级可以自己报名吗_初级会计考试可以自学吗?我刚完成报名
  9. 计算机对会计有什么好处,会计专业转行干过设计工作,这些宝贵经验和感悟,对你有用(三)...
  10. struts2不能请求路径