全面了解Maven依赖范围
Posted Huazie
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了全面了解Maven依赖范围相关的知识,希望对你有一定的参考价值。
Maven依赖范围
翻译原文详见 Maven Dependency Scopes
1. 总览
Maven 是 Java 生态系统中最流行的构建工具之一,其核心特性之一是依赖管理。
Maven is one of the most popular build tools in the Java ecosystem, and one of its core features is dependency management.
在本教程中,我们将描述和探索有助于管理 Maven 项目中的传递依赖关系的机制——依赖范围。
In this tutorial, we’re going to describe and explore the mechanism that helps in managing transitive dependencies in Maven projects — dependency scopes.
2. 传递依赖
Maven 中有两种依赖类型:直接(依赖)和 传递(依赖)
There are two types of dependencies in Maven: direct and transitive.
直接依赖项是我们明确包含在项目中的那些(依赖)。
Direct dependencies are the ones that we explicitly include in the project.
这些可以使用 <dependency>
标签包含:
These can be included using
<dependency>
tags:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
</dependency>
另一方面,直接依赖需要传递依赖。 Maven 会自动在我们的项目中包含所需的传递依赖项。
On the other hand, transitive dependencies are required by direct dependencies. Maven automatically includes required transitive dependencies in our project.
我们可以使用 mvn dependency:tree 命令列出项目中的所有依赖项,包括传递依赖项。
We can list all dependencies including transitive dependencies in the project using
mvn dependency:tree
command.
3. 依赖范围
依赖范围可以帮助限制依赖的传递性。他们还为不同的构建任务修改类路径。 Maven 有 六个 默认的依赖范围。
Dependency scopes can help to limit the transitivity of the dependencies. They also modify the classpath for different build tasks. Maven has six default dependency scopes.
(我们下面)重要的是要了解每个(依赖)范围(除了导入)都会对传递依赖项产生影响。
And it’s important to understand that each scope — except for import — has an impact on transitive dependencies.
3.1. Compile
当没有提供其他范围时,这是默认范围。
This is the default scope when no other scope is provided.
具有此范围的依赖项在所有构建任务中的项目类路径中都可用。它们也被传播到依赖项目中。
Dependencies with this scope are available on the classpath of the project in all build tasks. They are also propagated to the dependent projects.
更重要的是,这些依赖关系也是传递的:
More importantly, these dependencies are also transitive:
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
3.2. Provided
我们使用这个范围来标记应该由 JDK 或容器在运行时提供的依赖项。
We use this scope to mark dependencies that should be provided at runtime by JDK or a container.
此范围的一个很好的用例是部署在某个容器中的 Web 应用程序,其中容器本身已经提供了一些库。例如,这可能是一个已经在运行时提供 Servlet API 的 Web 服务器。
A good use case for this scope would be a web application deployed in some container, where the container already provides some libraries itself. For example, this could be a web server that already provides the Servlet API at runtime.
在我们的项目中,我们可以使用 provided 范围来定义这些依赖项:
In our project, we can define those dependencies with the provided scope:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
这 provided 的依赖项仅在编译时和项目的测试类路径中可用。这些依赖关系也不是传递的。
The provided dependencies are available only at compile time and in the test classpath of the project. These dependencies are also not transitive.
3.3. Runtime
运行时需要具有此范围的依赖项。但是我们不需要它们来编译项目代码。因此,标有 runtime 范围的依赖项将出现在运行时和测试类路径中,但它们将在编译类路径中丢失。
The dependencies with this scope are required at runtime. But we don’t need them for the compilation of the project code. Because of that, dependencies marked with the runtime scope will be present in the runtime and test classpath, but they will be missing from the compile classpath.
JDBC 驱动程序是一个很好的依赖关系示例,它应该使用 runtime 范围:
A JDBC driver is a good example of dependencies that should use the runtime scope:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
<scope>runtime</scope>
</dependency>
3.4. Test
我们使用此范围来指示在应用程序的标准运行时不需要依赖项,而仅用于测试目的。
We use this scope to indicate that dependency isn’t required at standard runtime of the application but is used only for test purposes.
测试依赖项不具有传递性,仅存在于测试和执行类路径中。
Test dependencies aren’t transitive and are only present for test and execution classpaths.
此范围的标准用例是向我们的应用程序添加一个测试库,例如 JUnit:
The standard use case for this scope is adding a test library such as JUnit to our application:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
3.5. System
system 范围与 provided 范围非常相似。主要区别在于 system 要求我们直接指向系统上的特定jar。
System scope is very similar to the provided scope. The main difference is that system requires us to directly point to a specific jar on the system.
值得一提的是,system 范围已被弃用。
It’s worthwhile to mention that system scope is deprecated.
(这里)重点是要记住,如果依赖项不存在或位于与 systemPath 指向的位置不同的位置,则使用系统范围依赖项构建项目可能会在不同的机器上失败:
The important thing to remember is that building the project with system scope dependencies may fail on different machines if dependencies aren’t present or are located in a different place than the one systemPath points to:
<dependency>
<groupId>com.baeldung</groupId>
<artifactId>custom-dependency</artifactId>
<version>1.3.2</version>
<scope>system</scope>
<systemPath>$project.basedir/libs/custom-dependency-1.3.2.jar</systemPath>
</dependency>
3.6. Import
它仅适用于依赖类型 pom。
It’s only available for the dependency type pom.
import 表示此依赖项应替换为其 POM 中声明的所有有效依赖项。
import indicates that this dependency should be replaced with all effective dependencies declared in its POM.
在这里,下面的自定义项目依赖项将替换为自定义项目的 pom.xml <dependencyManagement>
部分中声明的所有依赖项。
Here, below custom-project dependency will be replaced with all dependencies declared in custom-project’s pom.xml
<dependencyManagement>
section.
<dependency>
<groupId>com.baeldung</groupId>
<artifactId>custom-project</artifactId>
<version>1.3.2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
4. 范围和传递性
每个依赖范围都以自己的方式影响传递依赖。这就意味着不同的传递依赖可能最终在具有不同范围的项目中。
Each dependency scope affects transitive dependencies in its own way. This means that different transitive dependencies may end up in the project with different scopes.
但是,provided 和 test 范围的依赖项永远不会包含在主项目中。
However, dependencies with scopes provided and test will never be included in the main project.
让我们详细看看这意味着什么:
Let’s take a detailed look at what this means:
对于 compile 范围,所有具有 runtime 范围的依赖都会被拉入到项目中的 runtime 范围中,所有具有 compile 范围的依赖都会被拉入到项目中的 compile 范围中。
For the compile scope, all dependencies with runtime scope will be pulled in with the runtime scope in the project, and all dependencies with the compile scope will be pulled in with the compile scope in the project.
对于 provided 范围,runtime 和 compile 范围的依赖项都将与项目中 provided 范围一起引入。
For the provided scope, both runtime and compile scope dependencies will be pulled in with the provided scope in the project.
对于 test 范围,runtime 和 compile 范围的传递依赖都将与项目中的 test 范围一起引入。
For the test scope, both runtime and compile scope transitive dependencies will be pulled in with the test scope in the project.
对于 runtime 范围,runtime 和 compile 范围传递依赖项都将与项目中的 runtime 范围一起引入。
For the runtime scope, both runtime and compile scope transitive dependencies will be pulled in with the runtime scope in the project.
下面看下依赖范围图表
依赖范围 | 编译 | 测试 | 运行时 | 是否被打包 |
---|---|---|---|---|
compile | √ | √ | √ | √ |
provided | √ | √ | × | × |
runtime | × | √ | √ | √ |
test | × | √ | × | × |
system | √ | √ | × | √ |
5. 总结
在这篇快速文章中,我们专注于 Maven 依赖范围、它们的用途以及它们如何操作的细节。
In this quick article, we focused on Maven dependency scopes, their purpose and the details of how they operate.
以上是关于全面了解Maven依赖范围的主要内容,如果未能解决你的问题,请参考以下文章