1. Maven 依赖范围
概念
依赖范围(Dependency Scope)用于控制依赖在不同构建阶段的可见性和可用性。Maven 定义了几种不同的依赖范围,每种范围都有其特定的使用场景。
常见依赖范围及用途
compile
:默认的依赖范围,在所有的 classpath 中都可用,并且会传递到依赖的项目中。适用于项目的核心业务代码依赖。provided
:该依赖在编译和测试阶段可用,但在运行时由 JDK 或容器提供。例如 Servlet API,在 Tomcat 等容器中已经包含,不需要打包到项目中。runtime
:该依赖在运行和测试阶段需要,但在编译阶段不需要。例如 JDBC 驱动,编译时只需要 JDBC 接口,运行时才需要具体的驱动实现。test
:该依赖仅在测试编译和运行阶段可用,不会影响项目的正常运行。例如 JUnit 测试框架。system
:类似于provided
,但需要显式指定依赖的本地路径。这种方式不推荐使用,因为它破坏了 Maven 的依赖管理机制。import
:只能在<dependencyManagement>
中使用,用于导入其他pom.xml
的<dependencyManagement>
部分。
代码示例
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>dependency-demo</artifactId><version>1.0-SNAPSHOT</version><dependencies><!-- compile 范围 --><dependency><groupId>commons-lang</groupId><artifactId>commons-lang</artifactId><version>2.6</version></dependency><!-- provided 范围 --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version><scope>provided</scope></dependency><!-- runtime 范围 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.26</version><scope>runtime</scope></dependency><!-- test 范围 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency></dependencies>
</project>
2. Maven 依赖传递
概念
依赖传递是指当一个项目依赖另一个项目时,被依赖项目的依赖也会自动传递到当前项目中。这可以减少项目 pom.xml
中依赖声明的数量,但也可能导致依赖冲突。
代码示例
假设我们有三个项目:project-a
、project-b
和 project-c
。
project-b
的 pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>project-b</artifactId><version>1.0-SNAPSHOT</version><dependencies><dependency><groupId>commons-lang</groupId><artifactId>commons-lang</artifactId><version>2.6</version></dependency></dependencies>
</project>
project-a
的 pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>project-a</artifactId><version>1.0-SNAPSHOT</version><dependencies><dependency><groupId>com.example</groupId><artifactId>project-b</artifactId><version>1.0-SNAPSHOT</version></dependency></dependencies>
</project>
由于 project-a
依赖 project-b
,而 project-b
依赖 commons-lang
,所以 commons-lang
会通过依赖传递自动成为 project-a
的依赖。
3. Maven 依赖阻断
概念
依赖阻断是指在依赖传递过程中,通过某种方式阻止某些依赖传递到当前项目中。通常是因为这些依赖会导致冲突或不必要的开销。
代码示例
假设 project-c
依赖 project-b
,但不希望 project-b
的 commons-lang
依赖传递过来。
project-c
的 pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>project-c</artifactId><version>1.0-SNAPSHOT</version><dependencies><dependency><groupId>com.example</groupId><artifactId>project-b</artifactId><version>1.0-SNAPSHOT</version><!-- 排除 commons-lang 依赖 --><exclusions><exclusion><groupId>commons-lang</groupId><artifactId>commons-lang</artifactId></exclusion></exclusions></dependency></dependencies>
</project>
通过 <exclusions>
标签可以排除传递过来的依赖。
4. Maven 可选依赖
概念
可选依赖(Optional Dependencies)是指在声明依赖时,将其标记为可选。这样,当其他项目依赖当前项目时,这些可选依赖不会自动传递。
代码示例
假设 project-d
依赖 commons-lang
,并且将其标记为可选。
project-d
的 pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>project-d</artifactId><version>1.0-SNAPSHOT</version><dependencies><dependency><groupId>commons-lang</groupId><artifactId>commons-lang</artifactId><version>2.6</version><optional>true</optional></dependency></dependencies>
</project>
当其他项目依赖 project-d
时,commons-lang
不会作为传递依赖被引入。如果其他项目需要 commons-lang
,则需要显式声明该依赖。