maven import 重新下载_Maven入门6 - 依赖

传递依赖

若在项目A的POM中指定项目B为其依赖,那么项目B的所有依赖、从父项目继承的依赖、从依赖中继承的依赖,都对项目A可用。

即,A依赖B,B依赖C,只需在A中指定B为依赖项,A就可以使用B和C。

这种依赖传递的层次没有限制,不过遇到循环依赖可能会产生问题。

Maven是通过从本地仓库或远程仓库中读取每个项目的POM并解析,生成一棵依赖树来实现这一点的。

正是由于依赖的可传递性,一个项目包含的库可能会迅速庞大起来。有以下几种方式来解决此问题。

  • 依赖调解
  • 依赖管理
  • 依赖的作用范围
  • 依赖的排除
  • 可选依赖

注意,虽然Maven采用了传递依赖的机制,但是我们在需要某个依赖的时候,最好显式的引入,而不要使用传递依赖。因为一旦传递依赖有改变或被删除了,你的项目就构建不了。

直接显式引入依赖的另一个好处是能从POM或执行 mvn dependency:tree 命令了解更多信息。Maven还提供了 dependency:analyze 这个插件目标,用来分析依赖树。

依赖调解

当遇到同一个工件的多个版本作为依赖项时,将选择哪个版本的工件。Maven采用的是“最近的”,即依赖树中与项目最接近的版本。如果两个依赖版本在依赖树中处于同一深度,则第一个声明将获胜。

假设有如下项目依赖树:

6a82e0d2f189852cce9ab74c2f827d44.png

A到底用哪一个版本的D呢?A到D有两条路径:

A -> B -> C -> D

A -> E -> D

显然第二条路径中的D离A最近,所以Maven会选择1.0版本的D作为A的可用依赖。

如果你希望使用2.0版本的D,那么一种显而易见的方法就是直接在A中指定2.0版本的D为依赖项,即在 < dependencies > 元素中添加2.0版本的D,于是依赖树变成这样:

925bff5c32f58c4948d7a100d78010d6.png

此时,第三条路径中的D是离A最近的,因此Maven选择它作为可用依赖。

依赖管理

即 < dependencyManagement > 元素:主要是管理依赖的版本,包括直接指定的和传递的依赖,并不实际引入该依赖。我们仍然需要在 < dependencies > 元素中引入依赖,但可以不指定依赖的版本。

比如,我们将上面的2.0版本的D放在 < dependencyManagement > 元素中,而不是直接在 < dependencies > 元素中添加2.0版本的D,也可以实现让A采用2.0版本的D。

依赖管理经常用在父项目中,这样子项目的 < dependencies > 元素中的依赖就可以不必指定版本,而是从父项目的< dependencyManagement > 元素中获取依赖的版本,从而解决多个子项目的版本的一致性问题。

依赖的排除

通过在 < dependency > 元素中使用子元素 < exclusion > 就可以排除某个传递依赖,比如,X -> Y -> Z,那么我们在引入依赖Y的 < dependency > 元素中使用子元素 < exclusion > 排除Z,这样X就不会引入传递依赖Z。

可选(Optional)依赖

将依赖置为可选的,那么该依赖就不会传递了。即假如在Y的POM中,指定Z是可选依赖,那么当X引入Y时,就默认排除了Z,即不会引入Z。

依赖的作用范围(Scope)

依赖的作用范围是用来限制依赖的传递性的,同时决定了在哪个阶段引入依赖(即将依赖打包到classpath)。

Maven定义了6种作用范围:

  • compile :这是默认值,如果未指定作用范围,那么就采用此值。此类依赖将存在于构建的所有阶段。而且,此类依赖将会向上传递。
  • provided :表示在运行时你期望JDK或者容器来提供此依赖。所以,此类依赖只在编译和测试时引入,而在运行时是不引入的。同时,此类依赖没有传递性。一个例子是,Web项目可以将Servlet和Java EE相关的依赖设置为provided,因为在运行时,Web容器会提供这些类。
  • runtime :此类依赖只在运行时和测试时引入,而在编译时是不引入的。
  • test :此类依赖只在测试时引入,并且没有传递性。最常见的例子就是一些测试库,比如JUnit、Mockito等。
  • system :与provided类似,不同的是我们必须显式的提供包含该依赖的JAR包,表示运行时从指定路径获取该依赖,并不需要从仓库获取,而且该工件总是可用的。
  • import :此作用范围只能用在 < dependencyManagement > 部分中pom类型的依赖项,它表示该依赖项将被指定POM中 < dependencyManagement > 部分中的有效依赖项列表替换。

最后,给出各种作用范围对传递依赖的影响,即假设 A -> B -> C,那么 A 是否依赖于 C ,其作用范围是什么?

B -> C compile provided runtime test

A -> B

compile compile - runtime -

provided provided - provided -

runtime runtime - runtime -

test test - test -

系统依赖

即作用范围是 system 的依赖项。

注意,此作用范围已经被废弃(deprecated),即尽量少用。

系统依赖不会在仓库中查找。它们通常用于告诉Maven它们由JDK或VM提供,表示这些工件现在由JDK提供,但以前可以单独下载。典型的例子是JDBC标准扩展或Java身份验证和授权服务(JAAS)。

  ...  javax.sql      jdbc-stdext      2.0system${java.home}/lib/rt.jar  ...

如果工件由JDK的tools.jar提供,那么应该这样定义系统路径:

  ...  sun.jdk      tools      1.5.0system${java.home}/../lib/tools.jar  ...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值