在上一篇文章中我们已经介绍了依赖性,这次我们再来介绍下传递依赖的问题,首先我们还是在上篇文章基础之上进行编写。

1、上篇文章中已经建立了一个user-core的模块,现在首先再建立一个user-log的模块,在此模块中引入log4j、commons-logging等包:

 <dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.11</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.3</version>
</dependency>
</dependencies>

注意我们这里使用的log4j的版本和在user-core中使用的log4j的版本号是不同的哦。

为了方便我们在user-log中定义了一个Log类如下:

 package com.lq.wangzhen.user.log;

 public class Log {

     public void print(String str){
System.out.println("hello:"+str);
}
}

user-log的结构图如下:

2、下面再建立一个项目user-dao模块,在这个模块中我们要对user类进行操作,所以要导入user-core模块:

 <dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.lq.wangzhen.user</groupId>
<artifactId>user-core</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>

此时我们并没有在user-dao用引入hibernate的jar包,只是引用了user-core,但是我们也在user-dao中发现了hibernate的jar包,这个就是传递性依赖。

对于传递性依赖这里再做一点解释,就是这里user-core依赖于hibernate,而user-dao依赖于user-core,所以user-dao也会依赖于hibernate,这种依赖我们成为是基于compile的依赖,这个是通过scope进行配置的,我们可以在junit依赖中都配置了scope属性,如果此属性没有配置的话,则默认的是compile范围的,而对于scope为test类型的话,则不会进行传递依赖,比如下载我们把user-dao中依赖的junit去掉,如下:

 <dependencies>
<dependency>
<groupId>com.lq.wangzhen.user</groupId>
<artifactId>user-core</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>

此时只依赖了user-core,而user-core中依赖了junit,如下:

 <dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.2.5.Final</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.26</version>
</dependency>
</dependencies>

但是我们可以发现在其中配置了scope属性为test,所以不会发生传递依赖,即我们的user-dao项目中不会有junit的jar包:

可以发现其中并没有junit的jar包。

3、现在再让user-dao项目依赖user-log项目:

 <dependencies>
<dependency>
<groupId>com.lq.wangzhen.user</groupId>
<artifactId>user-core</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.lq.wangzhen.user</groupId>
<artifactId>user-log</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>

因为我们在user-core和user-log中都使用了log4j,并且user-core中使用的是1.2.17版本的,而user-log中使用的是1.2.11版本的,那此时在user-dao中最终会引用那个版本的呢?

我们可以看到引用的是user-core中的1.2.17版本的,这是为什么呢?此时我们把在user-dao中依赖user-core和user-log的顺序给调换一下,如下:

 <dependencies>
<dependency>
<groupId>com.lq.wangzhen.user</groupId>
<artifactId>user-log</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.lq.wangzhen.user</groupId>
<artifactId>user-core</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>

此时再观察结果:

此时我们可以看出这里引用的是user-log中的1.2.11版本的log4j,此时我们似乎明白了,在user-dao中先引用的是哪个项目就会使用此项目中的jar包,如果jar包有冲突的话。

4、到此,我们在以上项目的基础上再建立一个maven项目,命名为user-services,在此项目中依赖于user-dao,user-log,如下:

 <dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.lq.wangzhen.user</groupId>
<artifactId>user-dao</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.lq.wangzhen.user</groupId>
<artifactId>user-log</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>

此时先引用了user-dao,而在user-dao中先引用了user-core,所以user-dao中的log4j的版本是1.2.17版本的,而user-log中的log4j是1.2.11版本的,此时user-services中的log4j是哪个版本呢?我们看图:

这里发现引用的是1.2.11版本,这是为什么呢?我们明明是先引用的user-dao,而user-dao中的是1.2.17版本的,为什么是这个版本呢?这是因为:

user-core依赖于log4j 1.2.17

user-log依赖于log4j 1.2.11

user-dao依赖于user-core和user-log,最终依赖于log4j 1.2.17

user-services依赖于user-dao和user-log,此时从user-services找到log4j需要经过user-dao、user-core,需要两步,而从user-log找到log4j只需要一步,所以最终会选择user-log中的log4j,这是maven中的最小路径问题。那么这个选择我们能不能控制呢?当然!我们可以修改user-services中的pom.xml,在依赖于user-log时排除对log的依赖,如下:

 <dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.lq.wangzhen.user</groupId>
<artifactId>user-dao</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.lq.wangzhen.user</groupId>
<artifactId>user-log</artifactId>
<version>0.0.1-SNAPSHOT</version>
<exclusions>
18 <exclusion>
19 <groupId>log4j</groupId>
20 <artifactId>log4j</artifactId>
21 </exclusion>
22 </exclusions>
</dependency>
</dependencies>

这样user-services就会依赖于user-dao中的log4j了。

【Maven实战】传递性依赖的问题的更多相关文章

  1. Maven实战07_依赖

    1:依赖声明 <project> ... <dependencies> <dependency> <groupId>...</groupId> ...

  2. 学习笔记——Maven 如何处理传递性依赖

    maven引入的传递性依赖机制,一方面大大简化和方便了依赖声明,另一方面,大部分情况下我们只需要关心项目的直接依赖是什么,而不用考虑这些直接依赖会引入什么传递性依赖.但有时候,当传递性依赖造成问题的时 ...

  3. maven的传递性依赖

    一.概念: 假如有maven项目A,项目A依赖项目B,项目B依赖项目C,我们说A对B是第一直接依赖,B对C是第二直接依赖,那么他们的依赖关系:A---->B----->C,那么我们执行项目 ...

  4. 【Maven实战】依赖的范围

    在Maven中有三大模块,分别是依赖.仓库.生命周期和插件,我们接下来下来介绍下依赖,为了方便起见我们还是以案例来说: 1.首先建立一个maven项目,这里我建立一个user的项目 2.接下来我们在这 ...

  5. 【Maven实战】依赖的聚合和版本管理

    1.在之前的文章中,我们已经建立了四个Maven项目,但是此时如果我们要对这四个项目进行编译打包时,必须一个一个的进行执行命令,而聚合就是指只要我们在其中一个项目中编写一些代码,则在进行此项目的编译和 ...

  6. [Maven实战](9)传递性依赖

    了解Spring的朋友都知道.创建一个Spring Framework项目都须要依赖什么样的Jar包.假设不使用Maven,那么在项目中就须要手动下载相关的依赖.因为Spring Framework又 ...

  7. Maven实战读书笔记(三):Maven依赖

    3.1 依赖的配置 一个依赖声明可以包含下面元素: <dependencies> <dependency> <groupId></groupId> &l ...

  8. Maven实战:pom.xml与settings.xml

    pom.xml与settings.xml pom.xml与setting.xml,可以说是Maven中最重要的两个配置文件,决定了Maven的核心功能,虽然之前的文章零零碎碎有提到过pom.xml和s ...

  9. Maven实战(六)依赖

    我们项目中用到的jar包可以通过依赖的方式引入,构建项目的时候从Maven仓库下载即可. 1. 依赖配置    依赖可以声明如下: <project> ... <dependenci ...

随机推荐

  1. angularJS constant和value

    angularJS可以通过constant(name,value)和value(name,value)对于创建服务也是很重要的. 相同点是:都可以接受两个参数,name和value. 区别: 1.co ...

  2. 解决"the currently displayed page contains invalid values"

    原因是你的工程的根目录少了default.properties(有点项目工程这个文件名称是project.properties)这个文件,导致不能选择target:   解决办法: 在工程根目录下建立 ...

  3. rsyslog 报 WARNING: rsyslogd is running in compatibility mode.

      [root@localhost log]# uname -a Linux localhost.localdomain 2.6.32 #1 SMP Sun Sep 20 18:58:21 PDT 2 ...

  4. IDL实现主成分变化(PCA)

    IDL只能通过调用envi的二次接口做图像的变换,但是对于普通的数据没有提供函数.根据主成分变换的原理,用IDL写出来了,这样就不用每次再去用matlab的princomp去做了.主成分变化的基本过程 ...

  5. 如何解决eclipse上的Android程序“Please ensure that adb is correctly located at 'D:\eclipse\sdk\platform-tools\adb.exe' and can be executed.”小问题?

    首先,把运行的Android模拟器和eclipse一块儿关了, 然后win+R,cmd, 下面输入adb kill_server 再输入adb start_server 之后重新运行项目,不出意外的话 ...

  6. 面试题——分析从输入url到页面返回的过程(或者查询返回过程)

    1. You enter a URL into the browser(输入一个url地址) 2.The browser looks up the IP address for the domain ...

  7. 关于asp.net程序连接不了ORACLE数据库而PL/SQL可以连接的问题

    今天在发布ASP.NET WEB网站时发现程序连接不了数据 报“ORA-12154: TNS: 无法解析指定的连接标识符”的错误,但PL/SQL连接又没有问题.真莫名其秒.在百度找了好多相关的问题.都 ...

  8. propertychange input change

    IE678 支持propertychange事件,可以监听所有属性(包括自定义属性)的改变事件,包括手动修改输入框文本以及js修改输入框文本. propertychange事件有个特点就是不支持冒泡, ...

  9. Linux和windows下清除svn保存的账号密码信息

    linux是什么用户登录就是什么用户的home下,如root用户就是/root,如果xiangdong就是/home/xiangdong 用Svn时会有一种需求是需要换个帐号测试一下什么的,但往往有缓 ...

  10. for update和for update nowait的区别和使用

    首先,for update 和for update nowait 是对操作的数据行进行加锁,在事务提交前防止其他操作对数据的修改. for update 和for update nowait主要区别在 ...