【问题标题】:How do I stop gradle from upgrading transitive dependencies?如何阻止 gradle 升级传递依赖项?
【发布时间】:2020-05-08 21:15:57
【问题描述】:

为什么 Gradle 将我的库的传递依赖更改为更新版本?如何让它停止?

详情

我正在为我的公司开发一个使用 Spring Security 的内部插件库。该插件显式声明了对最新版本 Spring Security 4 的依赖:

    compile ('org.springframework.security:spring-security-core:4.2.13.RELEASE') {
        force = true
    }

当我在客户端项目中包含插件时,Gradle 正在将我从 spring security 4 升级到 5,这会破坏插件。

    compile 'com.mycompany:my-security-plugin:0.3.0-SNAPSHOT'

这是客户端项目中dependencyInsight的输出:

> Task :dependencyInsight
org.springframework.security:spring-security-core:5.1.6.RELEASE (selected by rule)
   variant "compile" [
      org.gradle.status             = release (not requested)
      org.gradle.usage              = java-api
      org.gradle.component.category = library (not requested)
   ]

org.springframework.security:spring-security-core:5.1.6.RELEASE
+--- org.springframework.security:spring-security-config:5.1.6.RELEASE
|    \--- com.mycompany:my-security-plugin:0.3.0-SNAPSHOT:20200122.162056-4 (requested org.springframework.security:spring-security-config:4.2.13.RELEASE)
|         \--- compileClasspath
\--- org.springframework.security:spring-security-web:5.1.6.RELEASE
     \--- com.mycompany:my-security-plugin:0.3.0-SNAPSHOT:20200122.162056-4 (requested org.springframework.security:spring-security-web:4.2.13.RELEASE) (*)

org.springframework.security:spring-security-core:4.2.13.RELEASE -> 5.1.6.RELEASE
\--- com.mycompany:my-security-plugin:0.3.0-SNAPSHOT:20200122.162056-4
     \--- compileClasspath

在我看来,在所有情况下,我都在我的配置中请求 spring security 4。我做错了什么?

我正在使用 Gradle 5.1.1。

更新

作为一种解决方法,可以让客户端应用程序使用特定版本声明对 Spring Security 的直接依赖。如果可能的话,我会尽量避免这种情况。

更新 2

gradlew dependencyInsight --dependency org.springframework.security:spring-security-web 的输出:

> Task :dependencyInsight
org.springframework.security:spring-security-web:5.1.6.RELEASE (selected by rule)
   variant "compile" [
      org.gradle.status             = release (not requested)
      org.gradle.usage              = java-api
      org.gradle.component.category = library (not requested)
   ]

org.springframework.security:spring-security-web:4.2.13.RELEASE -> 5.1.6.RELEASE
\--- com.mycompany:my-security-plugin:0.3.0-SNAPSHOT:20200122.162056-4
     \--- compileClasspath

更新 3

buildEnvironment 通过 grails 包括以下内容:

 +--- org.springframework.boot:spring-boot-gradle-plugin:2.1.9.RELEASE
|    |    +--- org.springframework.boot:spring-boot-loader-tools:2.1.9.RELEASE (*)
|    |    +--- io.spring.gradle:dependency-management-plugin:1.0.8.RELEASE

【问题讨论】:

  • 其他东西似乎正在引入org.springframework.security:spring-security-web:5.1.6.RELEASE(我从(*) 猜测作为提示),这反过来可能会引入org.springframework.security:spring-security-core:5.1.6.RELEASE,这会导致省略您的lib 依赖项。你能在org.springframework.security:spring-security-web:5.1.6.RELEASE 上执行dependencyInsight 并发布输出吗?
  • 发布了输出。谢谢
  • 显然您的插件正在使用较新的 Spring Security 版本的项目中使用。强制使用您的 Spring 安全版本将破坏该项目。该项目必须降级其依赖项,或者您必须在您的项目中升级它们(或使它们与两个版本的 Spring Security 一起工作)!。

标签: gradle spring-security grails-4


【解决方案1】:

我是否正确假设您使用 Spring 依赖管理插件 (io.spring.dependency-management) 以及 Spring Boot Gradle 插件 (org.springframework.boot)?那么这个组合很可能还会为您管理 spring-security-core 的最终版本,而不管您的构建设置请求的其他部分。

演示问题的最小设置

我有以下两个 Gradle 版本并排放置(为简洁起见,省略了 Gradle 5.1.1 Wrapper 文件):

my-security-plugin
└── build.gradle
my-client
├── build.gradle
└── settings.gradle

my-client 中运行以下 Gradle 命令给我(大致)与 OP 问题中相同的输出:

./gradlew dependencyInsight --configuration compile --dependency org.springframework.security:spring-security-core

my-security-plugin/build.gradle

plugins {
    id 'java'
}

group = 'com.mycompany'
version = '0.3.0-SNAPSHOT'

repositories {
    jcenter()
}

dependencies {
    compile ('org.springframework.security:spring-security-core:4.2.13.RELEASE') {
        force = true
    }
    compile 'org.springframework.security:spring-security-config:4.2.13.RELEASE'
    compile 'org.springframework.security:spring-security-web:4.2.13.RELEASE'
}

my-client/build.gradle

plugins {
    id 'java'
    id 'org.springframework.boot' version '2.1.7.RELEASE'
    id 'io.spring.dependency-management' version '1.0.9.RELEASE'
}

group = 'com.mycompany'
version = '1.0.0'

repositories {
    jcenter()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-security'
    compile 'com.mycompany:my-security-plugin:0.3.0-SNAPSHOT'
}

my-client/settings.gradle

includeBuild '../my-security-plugin'

此文件仅用于定义 Gradle 复合构建; includeBuild 不会出现在生产版本中,您宁愿将 my-security-plugin 发布到某个存储库,my-client 从那里下载它。

问题的可能解决方案

正如介绍中提到的,Spring Dependency Management Plugin 和 Spring Boot Gradle Plugin 的组合为您的构建定义了spring-security-core 的版本。除了您自己的解决方法之外,还有三种可能获得您想要的版本:

  1. 使用选择与您需要的spring-security-core 相同版本的Spring Boot 版本:id 'org.springframework.boot' version '1.5.22.RELEASE'
  2. Customize the managed versions 通过在您的构建中设置一个额外的属性:ext['spring-security.version'] = '4.2.13.RELEASE'
  3. 根本不要让 Spring 管理您的依赖项……

所有这些解决方案显然都有缺点:

  • 解决方案 1 强制您使用旧的 Spring Boot 版本
  • 解决方案 2 强制您在客户端应用程序中请求所需版本的传递依赖项(这类似于您自己想要避免的解决方法)
  • 解决方案 3 可能不值得手动管理所有 Spring 依赖项所产生的额外工作

现在你只需要选择较小的邪恶;-)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-17
    • 2019-10-31
    • 2020-07-04
    • 1970-01-01
    • 2016-03-21
    • 1970-01-01
    • 2012-12-05
    • 1970-01-01
    相关资源
    最近更新 更多