领先一步
VMware 提供培训和认证,助您加速进步。
了解更多本周,我们继续我们的 通往 GA 系列,探索 Spring Boot 4 中的模块化工作。
Spring Boot 1.0 于 2014 年发布时,它带有一个单一的 spring-boot-autoconfigure jar,大小为 182 KiB。当然,最初的版本不支持太多功能,但多年来,这种情况已经改变。
Spring 的最大优势之一是它支持大量技术,但每项新技术都会带来成本。每次我们支持新功能时,自动配置 jar 都会增长。对于 Spring Boot 3.5,单个 spring-boot-autoconfigure jar 现在已达 2 MiB!
虽然磁盘空间很便宜,但大多数类实际上对您来说并不重要,因为它们针对的是您的应用程序中可能没有的技术。这意味着您会得到大量关于不必要的类和配置属性的自动完成建议。这增加了混乱和心智负担,我们将在 Spring Boot 4 中改变这一点。
那么,泡一杯舒缓身心的茶,和我们一起踏上这段旅程吧!
在 Spring Boot 4 中,我们将对自动配置的打包、交付和使用方式进行根本性改变。我们不再使用单一的、庞大的 spring-boot-autoconfigure jar,而是将功能拆分为更小、更集中的模块。
这一变化是出于可维护性、清晰度和更精简的运行时占用空间。它对包结构、启动器以及最终用户如何从 Spring Boot 3 迁移到 Spring Boot 4 产生连锁反应。Spring Boot 支持的每项技术现在都有自己的启动器,其中一些是 Spring Boot 4 中新增的。
现在,您可能会问自己:为什么要这样做?为什么要触及代码库中的几乎所有内容并将其拆分?事实上,这是一项极具挑战性的工作,我们甚至在 Spring Boot 3.5 发布之前就开始了。然而,它的好处却非常引人注目。
可维护性和架构清晰度:通过更小的模块和强制的边界,团队和我们的贡献者可以更清晰地理解每个领域。模块边界成为契约而不是软约定。您的 IDE 也提供了更专注的视角。不再有您永远不需要的类的代码完成建议,只有您实际使用的配置属性会出现在 IDE 弹出窗口中。
减小 artifact 大小和占用空间:您的应用程序不再需要引入包含许多您可能不使用的功能的大型 autoconfigure jar,而是只引入相关的模块。这减少了类路径开销、启动扫描成本和磁盘空间。
更强的信号和避免意外的自动配置:由于模块是受作用域限制的,Spring Boot 对您引入依赖项的原因有了更强的信号。您是为了服务器端 @Controller 支持而包含了 spring-webflux jar,还是因为您想使用 WebClient?通过专注于模块,我们实际上知道了。您将永远不需要调用 SpringApplication.setWebApplicationType(WebApplicationType.NONE),因为如果您只通过新的 spring-boot-webclient 模块使用 WebClient,类路径上甚至不会有任何 Web 服务器自动配置。
启用新的用例:我们已经看到模块化开辟了新的用例,我们认为未来还会有更多。例如,您现在可以独立于 Actuator 使用 Micrometer 指标。您可以只引入发布指标的模块,而无需完整的 Actuator 依赖链,这在 Spring Boot 3 中很难实现。
事实证明,spring-boot-autoconfigure 并不是唯一需要模块化的 jar。虽然没有那么大,但 spring-boot-test-autoconfigure jar 也需要拆分。例如,@AutoConfigureDataJdbc 注解用于测试 Spring Data JDBC,因此它应该与 spring-boot-data-jdbc 模块对齐。
我们不希望将测试支持代码放在模块本身中,因此我们创建了测试专用的模块。对于上面的示例,该注解已移至 spring-boot-data-jdbc-test jar。
为了保持简单,我们还确保每个常规启动器都提供了一个测试启动器 POM。例如,如果您的应用程序依赖于 spring-boot-starter-webmvc,那么它也应该在 test 作用域中依赖 spring-boot-starter-webmvc-test。
将应用程序从 Spring Boot 3 迁移到 4 所需的工作量将因多种因素而异。对于大多数应用程序,我们希望这个过程只是对 pom.xml 或 build.gradle 文件进行一些更新,以及一些包导入修复。
以下是大多数应用程序应遵循的流程:
所有现有的启动器现在都传递性地引入了其相关模块。这意味着如果您已经在使用启动器,您的应用程序将拥有它所需的大部分模块。您可能需要做的一件事是为以前没有启动器的技术添加启动器。这是一个典型的 Spring Boot 3 Web 应用程序 Maven POM:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
在 Spring Boot 3 中,当 Flyway jar 存在时,Flyway 会自动配置。在 Spring Boot 4 中,您现在需要包含 Flyway 启动器以确保您拥有 spring-boot-flyway 模块。我们还借此机会重命名了一些启动器,使它们更具一致性。在这里,web 启动器现在被命名为 webmvc。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-flyway</artifactId>
</dependency>
您可以在迁移指南中找到每种技术的启动器列表。
您使用的每个主要启动器都有一个相应的测试启动器,您也需要添加它。这样做可以确保您获得正确的测试支持。请确保将测试启动器添加到 test 作用域。对于我们上面的示例应用程序,我们将使用以下测试启动器:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-flyway-test</artifactId>
<scope>test</scope>
</dependency>
这将包含您测试 Web 组件、控制器、模拟 MVC、安全性和 Flyway 所需的一切。
如果您的项目或任何自定义启动器以前依赖于 spring-boot-autoconfigure 或手动引入了自动配置类,您将需要将这些导入/依赖项替换为新的模块化等效项。
如果您引用 Spring Boot 的包,您还需要更新包名。由于模块现在以 org.springframework.boot.<module> 开头,因此自动配置支持类的导入可能需要更改。这也适用于自定义器,例如。
如果您的组织维护自定义 Spring Boot 启动器或共享依赖项,您应该根据模块化重新评估它们。由于包名和模块的重构,我们强烈不建议在同一 artifact 中同时支持 Spring Boot 3 和 4。
为了简化过渡,Spring Boot 4 保留了经典启动器 POM。这些“经典启动器”捆绑了所有(模块化)自动配置模块,但不包含它们的传递依赖项。实际上,如果您在升级时遇到问题,经典启动器可以作为有用的工具。您可以采用经典启动器来“启动并运行”,修复任何包导入,然后随着时间的推移,迁移到更具选择性的模块依赖项。要使用经典启动器,您的依赖项将如下所示:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-classic</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test-classic</artifactId>
<scope>test</scope>
</dependency>
Spring Boot 4 对自动配置的模块化是朝着更易于维护、可组合和精简的框架迈出的有意识的架构步骤。通过将功能拆分为专注的模块,引入经典启动器并提供测试启动器,Spring Boot 为您提供了增量升级路径的工具。尽管存在一些迁移开销(特别是对于自定义或深度耦合的代码),但其在清晰度、占用空间和运行时行为方面的好处使其成为一项值得的投资。
如果您正在计划迁移,请尝试只使用您需要的模块来创建更轻量、更富有表现力的应用程序。如果您需要更多时间来完成迁移,请使用经典启动器,并在您的日程安排允许时采用模块化。
一如既往,我们欢迎您提出任何反馈。如果您发现错误,请在我们的 GitHub 问题跟踪器上报告。感谢所有一直关注里程碑和发布候选版本并已经这样做的朋友。