如何阻止 gradle 升级传递依赖项?
How do I stop gradle from upgrading transitive dependencies?
为什么 Gradle 将我的库的传递依赖性更改为更新版本?我如何让它停止?
详情
我正在为我的公司开发一个使用 Spring 安全性的内部插件库。该插件明确声明了对最新版本 Spring Security 4:
的依赖
compile ('org.springframework.security:spring-security-core:4.2.13.RELEASE') {
force = true
}
当我将插件包含在客户端项目中时,Gradle 将我从 spring 安全级别升级到 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 安全 4。我做错了什么?
我正在使用 Gradle 5.1.1.
更新
作为解决方法,可以让客户端应用使用特定版本声明对 spring 安全性的直接依赖。如果可能的话,我正在努力避免这种情况。
更新 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
我假设您使用 Spring 依赖管理插件 (io.spring.dependency-management
) 并且可能还使用 Spring 启动 Gradle 插件 (org.springframework.boot
)?那么这个组合很可能还会为您管理 spring-security-core
的最终版本,而不管您的构建设置请求的其他部分是什么。
演示问题的最小设置
我有以下两个 Gradle 构建彼此相邻(为简洁起见省略 Gradle 5.1.1 包装文件):
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 依赖管理插件和 Spring 引导 Gradle 插件的组合定义了构建的 spring-security-core
版本。除了您自己的解决方法之外,还有三种可能性可以获得您想要的版本:
- 使用 Spring 引导版本,选择与您需要的
spring-security-core
相同的版本:id 'org.springframework.boot' version '1.5.22.RELEASE'
- Customize the managed versions 通过在构建中设置一个额外的 属性:
ext['spring-security.version'] = '4.2.13.RELEASE'
- 根本不要让 Spring 管理您的依赖项……
所有这些解决方案显然都有缺点:
- 解决方案 1 强制您使用旧的 Spring 引导版本
- 解决方案 2 强制您在客户端应用程序中请求传递依赖项的所需版本(这类似于您想要避免的解决方法)
- 解决方案 3 可能不值得手动管理所有 Spring 依赖项的额外工作
现在你只需要选择较小的邪恶;-)
为什么 Gradle 将我的库的传递依赖性更改为更新版本?我如何让它停止?
详情
我正在为我的公司开发一个使用 Spring 安全性的内部插件库。该插件明确声明了对最新版本 Spring Security 4:
的依赖 compile ('org.springframework.security:spring-security-core:4.2.13.RELEASE') {
force = true
}
当我将插件包含在客户端项目中时,Gradle 将我从 spring 安全级别升级到 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 安全 4。我做错了什么?
我正在使用 Gradle 5.1.1.
更新
作为解决方法,可以让客户端应用使用特定版本声明对 spring 安全性的直接依赖。如果可能的话,我正在努力避免这种情况。
更新 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
我假设您使用 Spring 依赖管理插件 (io.spring.dependency-management
) 并且可能还使用 Spring 启动 Gradle 插件 (org.springframework.boot
)?那么这个组合很可能还会为您管理 spring-security-core
的最终版本,而不管您的构建设置请求的其他部分是什么。
演示问题的最小设置
我有以下两个 Gradle 构建彼此相邻(为简洁起见省略 Gradle 5.1.1 包装文件):
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 依赖管理插件和 Spring 引导 Gradle 插件的组合定义了构建的 spring-security-core
版本。除了您自己的解决方法之外,还有三种可能性可以获得您想要的版本:
- 使用 Spring 引导版本,选择与您需要的
spring-security-core
相同的版本:id 'org.springframework.boot' version '1.5.22.RELEASE'
- Customize the managed versions 通过在构建中设置一个额外的 属性:
ext['spring-security.version'] = '4.2.13.RELEASE'
- 根本不要让 Spring 管理您的依赖项……
所有这些解决方案显然都有缺点:
- 解决方案 1 强制您使用旧的 Spring 引导版本
- 解决方案 2 强制您在客户端应用程序中请求传递依赖项的所需版本(这类似于您想要避免的解决方法)
- 解决方案 3 可能不值得手动管理所有 Spring 依赖项的额外工作
现在你只需要选择较小的邪恶;-)