1. 概述

在Maven中排除依赖是一个常见的操作。然而,当涉及到Maven插件时,这个过程会变得更加复杂。

2. 什么是依赖排除

Maven负责管理依赖的传递性。这意味着Maven可以根据我们添加的依赖自动添加所有所需的依赖。但在某些情况下,这种传递性可能会迅速增加依赖的数量,因为会添加级联依赖。

例如,如果我们有A → B → C → D这样的依赖关系,那么A将依赖于B、C和D。如果A只使用了B的一小部分,而这一部分并不需要C,那么我们可以告诉Maven忽略A中的B → C依赖。

因此,A只会依赖于B,不再依赖于C和D。这就叫作依赖排除。

3. 排除传递性依赖

我们可以使用<exclusions>元素来排除子依赖。这个元素包含对特定依赖的排除设置。简而言之,只需要在项目POM文件的<dependency>元素中添加一个<exclusions>元素即可。

commons-text依赖为例,假设我们的项目只使用commons-text的部分功能,这部分功能不需要commons-lang子依赖。我们只需在项目POM文件中commons-text依赖声明下方添加一个<exclusions>节,如下所示:

<project>
    ...
    <dependencies>
        ...
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-text</artifactId>
            <version>1.1</version>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.commons</groupId>
                    <artifactId>commons-lang3</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>
    ...
</project>

这样,当我们重新构建项目时,就会发现commons-text库被集成到了项目中,但commons-lang库没有。

4. 从插件中排除传递性依赖

到目前为止,Maven不支持直接从插件中排除依赖,且已经有一个问题提出了添加这个新功能的需求。本节我们将讨论一种方法,通过覆盖来排除插件中的直接依赖。

假设我们需要从Maven Surefire插件中排除JUnit 4.7依赖。

首先,我们必须创建一个名为dummy的模块,使其成为项目根POM的一部分。这个模块仅包含一个POM文件,内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://maven.apache.org/POM/4.0.0"
         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>org.apache.maven.surefire</groupId>
    <artifactId>surefire-junit47</artifactId>
    <version>dummy</version>
</project>

接下来,在我们希望禁用依赖的子POM中,我们需要调整Maven Surefire插件的声明,添加带有dummy版本的依赖:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>${surefire-version}</version>
            <configuration>
                <runOrder>alphabetical</runOrder>
                <threadCount>1</threadCount>
                <properties>
                    <property>
                        <name>junit</name>
                        <value>false</value>
                    </property>
                </properties>
            </configuration>
            <dependencies>
                <dependency>
                    <!-- Deactivate JUnit 4.7 engine by overriding it with an empty dummy -->
                    <groupId>org.apache.maven.surefire</groupId>
                    <artifactId>surefire-junit47</artifactId>
                    <version>dummy</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>

最后,当我们构建项目时,会看到Maven Surefire插件的JUnit 4.7依赖未被包含在项目中,排除工作正常。

5. 总结

在这篇快速教程中,我们解释了依赖排除的概念以及如何使用<exclusions>元素排除传递性依赖。此外,我们还展示了如何通过创建一个dummy模块来绕过插件中直接依赖的排除问题。代码示例可在GitHub上找到。