Gradle 依赖管理的改进

工程 | Andy Wilkinson | 2015年2月23日 | ...

Maven 的 依赖管理 包括物料清单 (BOM) 的概念。BOM 是一种特殊的 POM,用于控制项目依赖项的版本,并提供一个中心位置来定义和更新这些版本。

许多 Spring 项目(包括 Spring Framework、Spring Cloud、Spring Boot 和 Spring IO Platform)都提供了 BOM,以便为 Maven 用户简化操作。不幸的是,如果您使用 Gradle,事情就没那么容易了。

Gradle 中的依赖管理

Gradle 的依赖管理 使用 ResolutionStrategy 来控制项目的依赖项版本。这提供了强大的功能和灵活性,但没有提供一种方法来重用已经在 Maven BOM 中声明的依赖项管理。因此,您必须手动执行此操作。根据 BOM 的情况,这很容易导致您的 build.gradle 脚本中增加数十行代码,仅仅是为了重用一些现有的配置。

在 Gradle 中重用 BOM

Gradle 的关键优势之一是它可以轻松扩展,并且可以通过使用插件来定制其行为。我们利用了这一点,并为 Gradle 编写了一个 依赖管理插件。它与 Gradle 1.x 和 2.x 兼容。此插件允许您使用 Maven BOM 来控制构建的依赖项,只需几行代码即可。第一步是应用插件

buildscript {
  repositories {
    jcenter()
  }
  dependencies {
    classpath "io.spring.gradle:dependency-management-plugin:0.5.1.RELEASE"
  }
}

apply plugin: "io.spring.dependency-management"

应用插件后,您可以使用它来导入 Maven BOM

dependencyManagement {
  imports {
    mavenBom 'io.spring.platform:platform-bom:1.1.1.RELEASE'
  }
}

通过这种配置,您可以声明对 BOM 中任何内容的依赖项,而无需指定版本

dependencies {
    compile 'org.springframework:spring-core'
}

导入的 BOM 将控制依赖项的版本。如果这些依赖项在 BOM 中列出,它还将控制其传递依赖项的版本。

Gradle 中的排除

Gradle 可以从 Maven 存储库检索依赖项,并且它使用 Maven POM 文件中的元数据来执行此操作。但是,它并不遵循 Maven 的规则,而是对元数据应用了自己的、细微不同的语义。这会导致问题的一个领域是排除传递依赖项。这最好用一个简单的例子来说明。

假设一个模块依赖于几个 Spring Framework 模块,spring-corespring-beans,并且使用 SLF4J 而不是 Commons Logging。其 POM 中的依赖项看起来像这样

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-core</artifactId>
  <version>4.1.4.RELEASE</version>
  <exclusions>
    <exclusion>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging</artifactId>
    </exclusion>
  </exclusions>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-beans</artifactId>
  <version>4.1.4.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>jcl-over-slf4j</artifactId>
  <version>1.7.10</version>
</dependency>

如果 Maven 构建依赖于此模块,则其依赖项树将如下所示

\- com.example:my-library:jar:0.0.1-SNAPSHOT:compile
   +- org.springframework:spring-core:jar:4.1.4.RELEASE:compile
   +- org.springframework:spring-beans:jar:4.1.4.RELEASE:compile
   \- org.slf4j:jcl-over-slf4j:jar:1.7.10:compile
      \- org.slf4j:slf4j-api:jar:1.7.10:compile

commons-logging 未列出,因为它仅由 spring-core 依赖,并且在其中已将其排除。

等效 Gradle 构建的依赖项树如下所示

\--- com.example:my-library:0.0.1-SNAPSHOT
     +--- org.springframework:spring-core:4.1.4.RELEASE
     |    \--- commons-logging:commons-logging:1.2
     +--- org.springframework:spring-beans:4.1.4.RELEASE
     |    \--- org.springframework:spring-core:4.1.4.RELEASE (*)
     \--- org.slf4j:jcl-over-slf4j:1.7.10
          \--- org.slf4j:slf4j-api:1.7.10

尽管已排除,但这次列出了 commons-logging。这可能存在问题,因为它会使您的类路径充斥着不应存在的依赖项。您可以通过在 Gradle 构建中手动配置所需的排除项来解决此问题,但首先您必须知道应该排除哪些项,然后您必须经历配置它们的繁琐且容易出错的过程。

遵循 POM 的排除

依赖管理插件更改了 Gradle 处理 POM 排除的方式,使其行为与 Maven 中的行为相同。将插件应用于示例项目后,它不再引入 commons-logging

\--- com.example:my-library:0.0.1-SNAPSHOT
     +--- org.springframework:spring-core:4.1.4.RELEASE
     +--- org.springframework:spring-beans:4.1.4.RELEASE
     |    \--- org.springframework:spring-core:4.1.4.RELEASE
     \--- org.slf4j:jcl-over-slf4j:1.7.10
          \--- org.slf4j:slf4j-api:1.7.10

将插件与 Spring Boot 一起使用

此插件与 Spring Boot 的 Gradle 插件之间存在一些相似之处。例如,Spring Boot 插件也 允许在不指定版本的情况下声明依赖项,但是它不影响传递依赖项,也不遵循 Maven 排除。

在即将发布的 Spring Boot 1.3 中,我们 已删除 Boot 自身的依赖项管理,并开始改用依赖项管理插件。对于早期版本的 Spring Boot 用户,这两个插件可以很好地共存,您可以配置依赖项管理插件以使用 Spring Boot 的启动器 BOM

buildscript {
  repositories {
    jcenter()
  }
  dependencies {
    classpath "io.spring.gradle:dependency-management-plugin:0.5.1.RELEASE"
    classpath "org.springframework.boot:spring-boot-gradle-plugin:1.2.3.RELEASE"
  }
}

apply plugin: "io.spring.dependency-management"
apply plugin: "spring-boot"

repositories {
  jcenter()
}

dependencyManagement {
  imports {
    mavenBom 'org.springframework.boot:spring-boot-starter-parent:1.2.1.RELEASE'
  }
}

dependencies {
  compile "org.springframework.boot:spring-boot-starter-web"
}

了解更多

除了上面描述的功能之外,该插件还支持使用 BOM 的属性(覆盖属性并在 Gradle 构建中使用它们)、自动在 Gradle 生成的 POM 文件中包含依赖项管理元数据等等。请查看 README 以获取更多详细信息。

该插件是 Apache 许可的,并且位于 GitHub 上。GitHub 也用于 问题跟踪。我们始终欢迎功能建议、拉取请求和错误报告。

获取 Spring 新闻通讯

与 Spring 新闻通讯保持联系

订阅

领先一步

VMware 提供培训和认证,以加速您的进步。

了解更多

获取支持

Tanzu Spring 在一个简单的订阅中提供对 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件。

了解更多

即将举行的活动

查看 Spring 社区中所有即将举行的活动。

查看全部