Maven Dependency Mechanism
Maven Dependency Mechanism is one of the core features of the Apache Maven build tool. It can automatically download and manage the external libraries (JAR files) required by the project and their dependencies.
The Maven dependency mechanism greatly simplifies the build process of Java projects, allowing developers to avoid manually downloading and managing various third-party libraries.
Maven stores millions of open source libraries through the Maven Central Repository. When you declare a dependency in your project, Maven automatically downloads that library and all its dependencies from the repository.
Dependency Declaration
Declare it in pom.xml using the <dependency> tag:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
Basic Concepts of Maven Dependencies
1. Coordinate System (Coordinates)
Maven uses three basic coordinates to uniquely identify a dependency:
- groupId: Defines the organization or company to which the project belongs (e.g.,
org.apache) - artifactId: Defines the name of the project (e.g.,
commons-lang3) - version: Defines the version of the project (e.g.,
3.12.0)
Together these three elements form the unique identifier of a Maven dependency.
2. Dependency Scope
Maven defines different dependency scopes, which determine in which phases a dependency is available:
- compile(default): Available at compile, test, and runtime
- provided: Available at compile and test time, but provided by the JDK or container at runtime
- runtime: Only needed at test and runtime
- test: Only needed during test compilation and execution
- system: Similar to provided, but requires an explicit JAR path
3. Transitive Dependencies
When project A depends on project B, and project B depends on project C, Maven automatically introduces project C as a dependency of project A. This automatic dependency handling feature is called transitive dependencies.
The transitivity rules depend on Scope:
| Current Dependency Scope \ Transitive Dependency Scope | compile | provided | runtime | test |
|---|---|---|---|---|
| compile | compile | - | runtime | - |
| provided | provided | provided | provided | - |
| runtime | runtime | - | runtime | - |
| test | - | - | - | - |
How to Use Maven Dependencies in Projects
1. Adding Dependencies in pom.xml
In the Maven project'spom.xmlfile,<dependencies>section is used to declare project dependencies:
Example
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
</dependencies>
2. Dependency Exclusions
Sometimes you may need to exclude a transitive dependency; you can use<exclusions>tag:
Example
<groupId>com.example</groupId>
<artifactId>example-library</artifactId>
<version>1.0</version>
<exclusions>
<exclusion>
<groupId>org.unwanted</groupId>
<artifactId>unwanted-dependency</artifactId>
</exclusion>
</exclusions>
</dependency>
3. Dependency Management
In multi-module projects, you can use in the parent POM<dependencyManagement>to uniformly manage dependency versions:
Example
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.20</version>
</dependency>
</dependencies>
</dependencyManagement>
When child modules reference dependencies, they only need to declare groupId and artifactId, without specifying the version.
Advanced Features of Dependency Management
Dependency Version Management
UsedependencyManagementto uniformly manage versions:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.18</version>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 子模块使用时无需指定版本 -->
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
</dependencies>
BOM Import
Manage versions of a set of related dependencies:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.6.4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Optional Dependencies
Mark dependencies as optional and not transitive:
<dependency>
<groupId>com.example</groupId>
<artifactId>optional-lib</artifactId>
<version>1.0</version>
<optional>true</optional>
</dependency>
Maven Dependency Resolution Mechanism
1. Dependency Mediation
When version conflicts occur, Maven resolves them using the following rules:
- Nearest definition wins (the version with the shortest path in the dependency tree is selected)
- If the path length is the same, the dependency declared first takes precedence.
2. Impact of Dependency Scope
Dependencies with different scopes affect transitivity:
- compile scope dependencies are transitive
- provided and test scope dependencies are not transitive
- runtime scope dependencies are transitive with runtime scope
Final packaging results of dependencies with different scopes:
| Scope | Whether packaged | Typical use |
|---|---|---|
compile | Yes | Core dependencies |
provided | no | Provided by container |
runtime | Yes | Needed at runtime |
test | no | Unit tests |
3. Optional Dependencies
Dependencies marked as optional are not transitive:
Example
<groupId>com.example</groupId>
<artifactId>optional-lib</artifactId>
<version>1.0</version>
<optional>true</optional>
</dependency>
Commands Related to Dependencies
View dependency tree:
mvn dependency:tree
Analyze dependency issues:
mvn dependency:analyze
Download dependencies to directory:
mvn dependency:copy-dependencies
Maven Repository
1. Repository Types
- Local repository: Located in the user's home directory under
.m2/repositorydirectory - Central repository: Maven's default public repository
- Remote repository: A private repository built by a company or organization
2. Repository Configuration
You can configure inpom.xmlorsettings.xmlconfigure the repository:
Example
<repository>
<id>my-repo</id>
<url>http://repo.example.com/maven2</url>
</repository>
</repositories>
Best Practices
- Explicitly specify dependency versions: Avoid using dynamic versions such as LATEST or RELEASE
- Regularly update dependencies: Use
mvn versions:display-dependency-updatesto check available updates - Use BOM: For large frameworks (e.g., Spring), use a Bill of Materials to uniformly manage versions
- Clean up unused dependencies: Regularly run
mvn dependency:analyzeto check for unused dependencies