基本概念
前面我们已经写了两个简单的Maven项目,其中HelloFridend Maven项目就是依赖于Hello项目。Maven的项目依赖关系分为直接依赖和间接依赖,假设我们有这样一个问题背景有A、B、C三个Maven项目,其中A依赖于B,并且B依赖于C,那么其中的依赖关系如下。
- 直接依赖:
A->B、B->C - 间接依赖:
A->C
依赖的范围
根据依赖的范围大小分为compile(默认)、test、provided、runtime、import、system等。
其中最常用的是:compile、test、provided,并且只有范围为compile的依赖可以被其他Maven工程访问。
为了演示这个效果,首先我们创建两个Maven工程A和B。
然后在B中引入A的依赖。
pom文件如下所示:
pom(A).xml

pom(B).xml

然后然A和B项目重新加载Maven工程,当我们不指定依赖范围时:


可以看到在B的依赖关系中,不仅依赖于A还可以继承了A中的junit。
接下来我们将A中的junit依赖关系设置为test,然后重新加载A和B的Maven工程。
pom(A).xml

pom(B).xml

工程A的依赖。

工程B的依赖。

可以看到这个时候在B中只有A的依赖,junit依赖不见了,这个就是test与默认的compile的区别。
依赖冲突问题
前面的内容我们解决了依赖的传递范围问题,但是还有可能出现以下两种矛盾的情况:
A依赖B,B还依赖C,这个时候如果B和C中存在同名的依赖该如何处理,A中的依赖是谁的。A依赖B,A还依赖C,这个时候如果B和C中存在同名的依赖该如何处理,A中的依赖是谁的。
解决上述问题我们有一个口诀:路径最短者优先,路径相同时先声明者优先。
接下来创建实际的Maven项目进行测试。为了演示效果我们再创建一个名为C的Maven工程。
最短路径者优先
首先在C中引入依赖junit 4.9并且设置依赖范围为compile,然后在B中引入C的依赖和junit 4.13的依赖,接下来在A中引入B的依赖。
pom(C).xml

pom(B).xml

pom(A).xml

接下来重载所有的Maven工程。

然后查看每个工程的依赖情况如下:



可以看到A中最终获取到的junit版本为4.13,是从工程B中获取得到。
路径相同时先声明者优先
这个时候同样在C中引入依赖junit 4.9并且设置依赖范围为compile,然后在B中引入junit 4.13的依赖并且设置依赖范围为compile,接下来在A中同时引入B和C的依赖。
pom(C).xml

pom(B).xml

pom(A).xml

这个时候再次重新加载所有Maven工程,并查看所有工程的依赖关系如下。



这个时候可以看到在工程A中的junit版本为4.9说明A获取到的junit是从C中拿到的,因为我们在导入依赖时先声明的是工程C。
依赖的排除
前面的我们使得工程A依赖工程C,此时如果工程C中有junit并且可见性是compile这个时候工程A也会获取到C中对应的junit。有的时候我们只想依赖工程A但是不想获取工程C中的某个依赖,在无法修改其可见性时(例如:调用MySQL驱动包时想不获取其内部的某个子依赖),该如何操作?这个时候就需要使用到,依赖排除技术。
使用方式,在<dependency></dependency>内引用<exclusions></exclusions>标签。
演示效果如下:
pom(A).xml

pom(C).xml

重新加载工程A和工程C,查看其依赖情况。

此时,在工程A中就无法获取到工程C中的junit依赖。
统一管理目标Jar包的版本
以对Spring的jar包依赖为例:Spring的每一个版本中都包含spring-context,springmvc等jar包。我们应该导入版本一致的Spring jar包,而不是使用4.0.0的spring-context的同时使用4.1.1的springmvc。
比如现在xml如下所示,在使用相关依赖时,需要保证所有的依赖版本一致,例如此处都为4.0.0.RELEASE,一共有4个依赖,如果我们需要修改Spring的版本就需要同时修改所有的依赖版,如果是一个个的去改肯定不是我们写代码的思想,我们应该会想可不可以去定义一个变量,然后统一定义所有的版本号,这在.xml文件中也是有这样的操作。
1 | <dependency> |
可以使用<properties></properties>标签实现操作,然后在需要引用的地方使用${}形式进行引用。
如下所示:
1 | <properties> |
这样依赖,进行版本调整时只需要改一个地方即可。
以工程C进行演示,修改配置文件后,重新加载工程C。

可以看到,所有的版本全部都被修改为了4.0.0.RELEASE。