Maven的compile和runtime scopes之间的区别是什么?

23
在Maven项目的pom.xml文件中,我们可以在依赖项中使用compile和runtime作为作用域。这有什么重要意义?请提供一些适用的示例以便理解。

1
一种情况是在编译时才需要库文件,另一种情况则是在运行时需要。 - Dave Newton
2个回答

52
以下内容摘自Maven文档

compile

这是默认范围,如果没有指定则使用此范围。编译依赖项在项目的所有类路径中都可用。此外,这些依赖关系会传播到依赖项目。

runtime

此作用域表示依赖项不需要进行编译,但需要在执行时使用。它位于运行时和测试类路径中,但不在编译类路径中。

例如,如果我们在POM中有以下两个依赖项:

<dependency>
    <groupId>commons-logging</groupId>
    <artifactId>commons-logging-api</artifactId>
    <version>1.1.3</version>
    <scope>compile</scope> <!-- can be ommitted as it is the default -->
</dependency>
<dependency>
    <groupId>commons-logging</groupId>
    <artifactId>commons-logging</artifactId>
    <version>1.1.3</version>
    <scope>runtime</scope>
</dependency>

如果我在我的项目的一个类中偶然地直接引用了commons-logging的一个类,那么编译我的模块时,来自commons-logging-api的类将会在类路径上,而来自commons-logging的类将不可用,因此构建将失败。

但是在运行时或测试编译和执行期间,commons-logging的类将位于类路径上,因此可以使用(即由commons-logging-api的类或项目的测试直接使用)。

Maven在另一个项目中引用您的项目作为依赖项时,compileruntime依赖项都包括传递性(在相同的范围下)。

p.s. 如kostja所述,还有provided范围

  

provided

     

这与compile非常相似,但表明您希望JDK或容器在运行时提供依赖项。例如,在为Java Enterprise Edition构建Web应用程序时,您会将Servlet API和相关的Java EE API的依赖关系设置为provided范围,因为Web容器提供这些类。此范围仅在编译和测试类路径上可用,并且不具有传递性。

基本上,provided和compile之间的区别在于提供的依赖项没有传递性。


1
想象一下,你正在将应用程序部署到符合Java EE标准的服务器上。服务器提供了实现Java EE标准的所有库,因此您不需要将它们与应用程序一起部署。
在开发过程中,您需要具有编译时范围的Java EE库,因为您需要编译类。
但是在运行时,依赖项由应用程序服务器提供。Maven在这种情况下使用“provided”范围。

能否更新您的答案,提供一个相反的例子——仅在运行时指定依赖项。或者这完全是无效的情况吗? - Gautam
2
如果服务器/容器在运行时已经提供了这些依赖项,那么我们将保持范围为“provided”,而不是编译。 - vaibhav.g

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接