为什么 Spring Boot 启动依赖项的设计目的与 Maven 传递依赖机制的既定意图相反?

2024-03-16

根据Maven 依赖文档 http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Scope其目的是显式列出所有编译依赖项,而不是在编译时传递使用:

其目的是 [传递编译依赖项] 应该是运行时范围,以便必须显式列出所有编译依赖项 - 但是,在某些情况下,您依赖的库扩展了另一个库的类,迫使您可以在编译时间。因此,即使编译时依赖项是可传递的,编译时依赖项仍保留为编译范围。

Spring Boot 有一个“Starter”依赖项的概念。从 Spring Boot 自己的文档(以及我在 Spring Boot 自己的示例和其他地方看到的许多使用示例)来看,很明显,它们旨在传递性地引入许多其他依赖项,以便在运行时和编译时使用。每Spring Boot 的文档 http://docs.spring.io/spring-boot/docs/1.5.1.RELEASE/reference/htmlsingle/#using-boot-starter:

Starters 是一组方便的依赖描述符,您可以将其包含在应用程序中。您可以获得所需的所有 Spring 和相关技术的一站式服务,而无需寻找示例代码并复制粘贴依赖描述符负载。例如,如果您想开始使用 Spring 和 JPA 进行数据库访问,只需在项目中包含 spring-boot-starter-data-jpa 依赖项即可。

启动器包含许多使项目快速启动和运行所需的依赖项,并具有一致的、受支持的托管传递依赖项集。

使用这种机制来传递编译范围的依赖项似乎与 Maven 官方打算如何使用它们的意图不一致。 Maven 是一个非常清楚地说明这一点的地方依赖性:分析 https://maven.apache.org/plugins/maven-dependency-plugin/analyze-mojo.html插件目标,直接使用 Maven 启动器依赖项时会显示警告。例如,运行mvn dependency:analyzeSpring Boot 自己的“入门 https://spring.io/guides/gs/spring-boot/" 示例生成以下输出:

[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 Boot 启动器模式的设计方式与底层构建系统的既定意图直接相反。是否有关于该主题的任何发布的讨论或在任何地方给出的解释?


这个问题是在 Spring Boot 项目中作为一个问题提出的弹簧启动#8341 https://github.com/spring-projects/spring-boot/issues/8341。几位 Spring Boot 开发人员对此问题做出了回应,表示这实际上并不是对 Maven 依赖机制的滥用。

Comment https://github.com/spring-projects/spring-boot/issues/8341#issuecomment-281178884:

为什么 Spring Boot 启动器模式的设计方式与底层构建系统的意图直接相反?

IMO,您对 Maven 文档中的一句话读得太多了。我认为这很能说明问题,甚至警告你必须选择加入。

有没有理由认为这种滥用是“可以”的?

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

是否有一种“正确”的方式可以更好地实现此功能(使用单个简单的 Maven 配置在已知版本上方便地提供一组依赖项)?

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

Comment https://github.com/spring-projects/spring-boot/issues/8341#issuecomment-281300623:

您过度阅读了这一点,并且您的观点在我看来缺乏实用性。 dependency:analyze 目标是为用户提供一种方法来检测您的编译类路径仅包含您实际需要的内容。文档中的这句话只是为了解释为什么编译范围也是传递的。

[...]

回想起来,您遇到的是 Maven 问题,而不是 Spring Boot 问题,因为大量不使用 Spring Boot 的项目本身并未列出所有编译依赖项。

根据此反馈,票MDEP-557 https://issues.apache.org/jira/browse/MDEP-557已为 Maven 依赖项插件创建,以便不对这些传递依赖项的使用发出警告。

因此,为了回答这个问题,Spring Boot 团队认为这是传递依赖的适当用法,并且这并不违背 Maven 的意图。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 Spring Boot 启动依赖项的设计目的与 Maven 传递依赖机制的既定意图相反? 的相关文章

随机推荐