【Maven实战】传递性依赖的问题
在上一篇文章中我们已经介绍了依赖性,这次我们再来介绍下传递依赖的问题,首先我们还是在上篇文章基础之上进行编写。
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实战】传递性依赖的问题的更多相关文章
- Maven实战07_依赖
1:依赖声明 <project> ... <dependencies> <dependency> <groupId>...</groupId> ...
- 学习笔记——Maven 如何处理传递性依赖
maven引入的传递性依赖机制,一方面大大简化和方便了依赖声明,另一方面,大部分情况下我们只需要关心项目的直接依赖是什么,而不用考虑这些直接依赖会引入什么传递性依赖.但有时候,当传递性依赖造成问题的时 ...
- maven的传递性依赖
一.概念: 假如有maven项目A,项目A依赖项目B,项目B依赖项目C,我们说A对B是第一直接依赖,B对C是第二直接依赖,那么他们的依赖关系:A---->B----->C,那么我们执行项目 ...
- 【Maven实战】依赖的范围
在Maven中有三大模块,分别是依赖.仓库.生命周期和插件,我们接下来下来介绍下依赖,为了方便起见我们还是以案例来说: 1.首先建立一个maven项目,这里我建立一个user的项目 2.接下来我们在这 ...
- 【Maven实战】依赖的聚合和版本管理
1.在之前的文章中,我们已经建立了四个Maven项目,但是此时如果我们要对这四个项目进行编译打包时,必须一个一个的进行执行命令,而聚合就是指只要我们在其中一个项目中编写一些代码,则在进行此项目的编译和 ...
- [Maven实战](9)传递性依赖
了解Spring的朋友都知道.创建一个Spring Framework项目都须要依赖什么样的Jar包.假设不使用Maven,那么在项目中就须要手动下载相关的依赖.因为Spring Framework又 ...
- Maven实战读书笔记(三):Maven依赖
3.1 依赖的配置 一个依赖声明可以包含下面元素: <dependencies> <dependency> <groupId></groupId> &l ...
- Maven实战:pom.xml与settings.xml
pom.xml与settings.xml pom.xml与setting.xml,可以说是Maven中最重要的两个配置文件,决定了Maven的核心功能,虽然之前的文章零零碎碎有提到过pom.xml和s ...
- Maven实战(六)依赖
我们项目中用到的jar包可以通过依赖的方式引入,构建项目的时候从Maven仓库下载即可. 1. 依赖配置 依赖可以声明如下: <project> ... <dependenci ...
随机推荐
- DataGridView绑定BindingList<T>带数据排序的类
本文章转载:http://yuyingying1986.blog.hexun.com/30905610_d.html DataGridView绑定List<T>类时候,不会自动的进行排序. ...
- WinForm(C#)CheckedlistBox绑定数据,并获得选中的值(ValueMember)和显示文本(DisplayMember)
本文中我将和大家讨论关于在WinForm开发中给CheckedlistBox空间绑定数据源,并获取控件中选中的所有元素的显示文本(DisplayMember)和对应的实际值(ValueMember)的 ...
- Android 通过反射让SQlite建表如此简单
我们通常使用SQlite的时候,假设我们有10张表,我们要写10个建表语句.而建表语句中仅仅有一些字段的名字须要改而已,这样既费时又费力,还easy出错.我们知道写sql语句的时候常常会写错,假设写错 ...
- css3之 media query 使用(转)
原文链接:http://www.moke8.com/article-5657-1.html 讲到响应式布局, 相信大家都有一定的了解,响应式布局是今年很流行的一个设计理念,随着移动互联网的盛行,为解决 ...
- C++面试中string类的一种正确写法
C++ 的一个常见面试题是让你实现一个 String 类,限于时间,不可能要求具备 std::string 的功能,但至少要求能正确管理资源.具体来说: 能像 int 类型那样定义变量,并且支持赋值. ...
- Servlet与JSP的关系
Servlet与JSP的异同点: 相似点: 都可以生成动态网页 不同点: JSP擅长网页制作,生成页面直观,但不易追踪与排错 Servlet是纯Java,擅长处理流程与业务逻辑,缺点是页面不直观
- Java基础知识强化17:JAVA不可以将所覆盖的方法的访问权限变得比父类的小
首先我们看一下下面的代码如下: interface I { void go(); } abstract class A implements I { } class C extends A { voi ...
- Linux shell入门基础(八)
八.shell脚本sed&awk 01.sed的使用 流编辑器-Steam Editor #ed /etc/passwd 1,10p …… 1s/root/byf/p(替换root为byf) ...
- Composite 组合模式
简介 <大话设计模式>一书中组合模式的定义为:将对象组合成[树]形结构以表示[部分-整体]的层次结构,组合模式使得用户对[单个对象]和对[组合对象]的使用具有一致性. ...
- INSTALL_PARSE_FAILED_MANIFEST_MALFORMED 错误
在eclipse编译好文件之后,往AVD中安装apk,报错如下:INSTALL_PARSE_FAILED_MANIFEST_MALFORMED一般来说只需要检查AndroidManifest.xml中 ...