Maven的依赖范围Scope详解

一、引入依赖范围的原因

1 例如Junit,将Junit的jar包打包到发布包是没有必要的。

2 例如servlet-api,为了编译通过,我们引入servlet-api jar包;但因为web容器也会提供servlet-api,如果将servlet-api打包至WAR包,就会造成依赖冲突。

示例:

<dependency>  
  <groupId>junit</groupId>  
  <artifactId>junit</artifactId>  
  <version>4.4</version>  
  <scope>test</test>  
</dependency>
<dependency>  
  <groupId>javax.servlet</groupId>  
  <artifactId>servlet-api</artifactId>  
  <version>3.1</version>  
  <scope>provided</scope>  
</dependency>


二、scope范围依赖

1 complie

默认值。参与当前项目的编译,后续的测试,运行,是一个比较强的依赖。

2 test

参与包括测试代码的编译,执行。比较典型的如junit。

3 runtime

被依赖项目无需参与项目的编译,不过后期的测试和运行周期需要其参与。
与compile相比,跳过编译而已.
oracle jdbc驱动架包就是一个很好的例子,一般scope为runntime。另外runntime的依赖通常和optional搭配使用,optional为true。我可以用A实现,也可以用B实现。

4 provided

打包的时候不包进去,别的设施(如Web Container)会提供。
事实上该依赖理论上可以参与编译,测试,运行等周期。
相当于compile,但是在打包阶段做了exclude的动作。

5 system

从参与度来说,也provided相同,不过被依赖项不会从maven仓库抓,而是从本地文件系统拿,一定需要配合systemPath属性使用。

 

依赖范围及作用

依赖范围(scope)主源码classpath可用测试源码classpath可用会被打包
compile 缺省值TRUETRUETRUE
testFALSETRUEFALSE
runtimeFALSETRUETRUE
providedTRUE(外界提供)TRUEFALSE

scope的依赖传递

A–>B–>C。当前项目为A,A依赖于B,B依赖于C。知道B在A项目中的scope,那么怎么知道C在A中的scope呢?答案是:
当C是test或者provided时,C直接被丢弃,A不依赖C;
否则A依赖C,C的scope继承于B的scope。