我们经常写 Maven
依赖。很少去关注 Maven
依赖的作用域问题,更多的关注的所依赖jar包的版本问题。
比如我们在pom文件中加入一个依赖,一般都是这样写。
<dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-streaming-kafka-0-10_2.11</artifactId> <version>2.4.4</version> </dependency>
里面根本没有体现作用域的信息。所以很多人不是很关心依赖的作用域。其实上面这个依赖的作用域是 compile
的。因为 Maven
是约定大于配置,所以上面这个pom依赖是使用了默认的依赖作用域。
下面来简单总结一下 Maven
依赖的作用域。要想说明白作用域问题,先得弄清楚 Maven
项目的生命周期。大致可以分为这么几个阶段 编译》测试》打包》运行
。
Maven
依赖的作用域范围可以表示为 compile,test,runntime,provided,system
。
最常用的就是 compile
,如果不配置 scope
项则默认就 compile
的。 compile
表示被依赖的Jar包,参与当前项目的编译,并且后续的测试和运行阶段也参与其中。
表示依赖项目仅参与测试阶段相关的工作,包括测试代码的编译,执行。比如
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency>
表示依赖项目并不参与项目的编译阶段工作,但是后续的测试和运行阶段的工作要其参与其中。这个作用域日常工作中使用的比较少。
provided
作用范围跟 compile
类似,唯一的区别就是在打包的时候会跳过作用域是 provided
的项目,也就是最终不会被打进Jar包。比如
<dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-streaming_2.11</artifactId> <version>2.4.4</version> <scope>provided</scope> </dependency>
因为spark的运行环境会提供spark-streaming的相关jar包,所以无需一起打包。
与 provide
的作用范围类似,唯一的区别就是不会从 Maven
仓库抓取Jar包,而是从本地文件系统获取。日常工作很少用到。
scope
的依赖传递问题
假设当前项目为A,A依赖于B,B依赖于C。如果知道B在A项目中的 scope
,那么怎么知道C在A中的 scope
呢?
如果当C是 test
或者 provided
时,C直接被丢弃,A不依赖C;否则A依赖C,C的 scope
继承于B的 scope
。