Links#
https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html
https://maven.apache.org/plugins/maven-dependency-plugin/
https://maven.apache.org/enforcer/maven-enforcer-plugin/
1. Important Points#
dependencyManagement:
管理默认版本,不自动引入 jar
transitive dependency:
依赖的依赖,会被 Maven 递归解析进项目
dependency mediation:
多个版本冲突时 Maven 选择最终版本的规则
2. Scope#
| Scope |
Included In Runtime |
Typical Use |
compile |
yes |
default |
provided |
no |
Servlet API, container provides it |
runtime |
yes |
JDBC driver |
test |
no |
JUnit, Mockito |
import |
no |
BOM import only |
3. BOM#
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.3.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
BOM:
Bill Of Materials
一组经过配套测试的 dependency versions
4. Version Selection#
Maven mediation:
nearest definition wins
same distance uses first declaration
dependencyManagement can define the version used by transitive dependencies
./mvnw dependency:tree
./mvnw dependency:tree -Dincludes=com.fasterxml.jackson.core:jackson-databind
5. Version Override For Vulnerability#
scenario:
app-framework -> vulnerable-lib:1.0.0
vulnerable-lib:1.0.0 has CVE
app-framework cannot be upgraded today
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.example</groupId>
<artifactId>vulnerable-lib</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>
</dependencyManagement>
workflow:
find path with dependency:tree
prefer upgrading direct dependency first
if blocked, override transitive dependency in dependencyManagement
run unit tests and integration tests
verify with dependency scanner
record why the override exists
6. Exclusions#
<dependency>
<groupId>org.example</groupId>
<artifactId>app-framework</artifactId>
<version>2.0.0</version>
<exclusions>
<exclusion>
<groupId>org.example</groupId>
<artifactId>bad-lib</artifactId>
</exclusion>
</exclusions>
</dependency>
use exclusion when:
the transitive jar must not be present
another compatible implementation replaces it
version override cannot solve the conflict
avoid exclusion when:
only the version is old
runtime behavior is unknown
7. Optional Dependency#
<dependency>
<groupId>org.example</groupId>
<artifactId>optional-client</artifactId>
<version>1.0.0</version>
<optional>true</optional>
</dependency>
optional:
当前项目可用
下游项目不会自动继承这个 transitive dependency
8. Enforcer Checks#
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.5.0</version>
<executions>
<execution>
<id>enforce</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<dependencyConvergence/>
<requireJavaVersion>
<version>[21,)</version>
</requireJavaVersion>
</rules>
</configuration>
</execution>
</executions>
</plugin>
9. Checklist#
check:
no dynamic versions
direct dependencies have clear owners
BOM imported before manual overrides are reviewed
vulnerability overrides have comments or PR notes
dependency:tree output is checked for critical libraries