为什么 Spring Boot starter 依赖项被设计成与 Maven 的传递依赖项机制的既定意图相反的用途?

Why were Spring Boot starter dependencies designed to be used contrary to the stated intent of Maven's transitive dependency mechanisms?

根据 Maven dependency documentation 的目的是明确列出所有编译依赖项,而不是在编译时传递使用:

it is intended that [transitive compile dependencies] should be runtime scope instead, so that all compile dependencies must be explicitly listed - however, there is the case where the library you depend on extends a class from another library, forcing you to have available at compile time. For this reason, compile time dependencies remain as compile scope even when they are transitive.

Spring Boot 具有 "Starter" 依赖项的概念。从 Spring Boot 自己的文档(以及我在 Spring Boot 自己的示例和其他地方看到的许多使用示例),很明显这些是为了传递引入许多其他依赖项在运行时和编译时使用。每 Spring Boot's documentation:

Starters are a set of convenient dependency descriptors that you can include in your application. You get a one-stop-shop for all the Spring and related technology that you need, without having to hunt through sample code and copy paste loads of dependency descriptors. For example, if you want to get started using Spring and JPA for database access, just include the spring-boot-starter-data-jpa dependency in your project, and you are good to go.

The starters contain a lot of the dependencies that you need to get a project up and running quickly and with a consistent, supported set of managed transitive dependencies.

使用这种机制传递地引入编译范围的依赖项似乎与 Maven 官方打算如何使用它们的意图不一致。一个非常清楚的地方是 Maven dependency:analyze plugin goal, which displays warnings when the Maven starter dependencies are used directly. For instance, running mvn dependency:analyze on Spring Boot's own "Getting Started" 示例生成以下输出:

[WARNING] Used undeclared dependencies found:
[WARNING]    org.springframework:spring-web:jar:4.3.6.RELEASE:compile
[WARNING]    org.springframework.boot:spring-boot-test:jar:1.5.1.RELEASE:test
[WARNING]    org.springframework.boot:spring-boot-test-autoconfigure:jar:1.5.1.RELEASE:test
[WARNING]    org.springframework:spring-test:jar:4.3.6.RELEASE:test
[WARNING]    org.springframework.boot:spring-boot:jar:1.5.1.RELEASE:compile
[WARNING]    org.hamcrest:hamcrest-library:jar:1.3:test
[WARNING]    org.springframework:spring-context:jar:4.3.6.RELEASE:compile
[WARNING]    junit:junit:jar:4.12:test
[WARNING]    org.springframework.boot:spring-boot-autoconfigure:jar:1.5.1.RELEASE:compile
[WARNING]    org.springframework:spring-beans:jar:4.3.6.RELEASE:compile
[WARNING] Unused declared dependencies found:
[WARNING]    org.springframework.boot:spring-boot-starter-web:jar:1.5.1.RELEASE:compile
[WARNING]    org.springframework.boot:spring-boot-starter-test:jar:1.5.1.RELEASE:test
[WARNING]    org.springframework.boot:spring-boot-starter-actuator:jar:1.5.1.RELEASE:compile

我的问题是,为什么 Spring 引导启动模式的设计方式与底层构建系统的既定意图直接相反。是否有关于该主题的任何已发布讨论或任何地方给出的解释?

您似乎已将依赖插件配置为在出现警告时失败。如果您没有明确声明传递依赖项,我认为依赖项插件会发出警告。

尝试改变 <failOnWarning>true</failOnWarning><failOnWarning>false</failOnWarning>

这个问题是作为 Spring 引导项目 spring-boot#8341 中的一个问题提出的。几位 Spring 引导开发人员回应了这个问题,表明他们认为这实际上不是对 Maven 依赖机制的滥用。

Comment:

Why was the Spring Boot starter pattern was designed in such a way to be directly contrary to the intent of the underlying build system?

IMO,您对 Maven 文档中的一句话读得太多了。我认为这是在告诉你甚至要被警告你必须选择加入。

Is there a reason it was felt that this misuse is "OK"?

滥用是相当主观的。我不认为首发是滥用。如果这样做,那么您可以自由地显式声明所有编译依赖项。

Is there a "correct" way that this functionality — conveniently providing a set of dependencies at set known versions with a single simple Maven configuration — would better be implemented?

我不这么认为,这可能是传递编译依赖项保留在编译范围内并且默认情况下不生成警告的一个很好的原因。

Comment:

You are overreading this and your point of view lack of practicability IMO. The dependency:analyze goal was a mean to offer users a way to detect that your compilation classpath only contains what you actually need. This sentence in the doc is merely there to explain why the compile scope is transitive as well.

[...]

In retrospective, you're having a Maven question and not a Spring Boot questions because tons of projects out there not using Spring Boot do not list all their compile dependencies themselves.

根据此反馈,已为 Maven 依赖插件创建票证 MDEP-557,以便不对这些传递依赖项的使用发出警告。

所以,为了回答这个问题,Spring 引导团队认为这是对传递依赖项的一种恰当使用,而且这并不违背 Maven 的意图。