Spring Boot 4和Spring Framework 7帶來基礎要求升級、模塊化改進、API版本化、聲明式HTTP客戶端、彈性注解等重大特性,標志著Java開發生態向云原生時代的深度進化。
近日,Spring生態迎來了自2022年以來最具里程碑意義的更新——Spring Boot 4和Spring Framework 7的正式發布。這兩個版本延續了Spring團隊的現代化征程,不僅采納了最新的Java語言特性,還與Jakarta EE 11實現了更緊密的整合,同時顯著提升了開發效率并為應用提供了更強的彈性支持。本文將深入解析這兩個版本的核心特性,幫助開發者全面把握這次升級帶來的變革。
基礎要求全面升級
Spring Boot 4和Spring Framework 7在基礎要求上有了顯著提升。雖然Java 17仍然是最低要求,但官方強烈推薦使用Java 21或Java 25以充分利用虛擬線程等新JVM特性。Spring Framework 7全面采用了Jakarta EE 11標準,這意味著開發者將使用Servlet 6.1、JPA 3.2和Bean Validation 3.1等最新規范。對于Kotlin開發者,新版本支持Kotlin 2.2及以上版本,提供了更流暢的協程集成和響應式代碼編寫體驗。
Spring Boot 4的重大改進
作為第四個主要版本,Spring Boot 4在性能、可觀察性、可維護性和配置支持方面都有顯著增強。
在本地鏡像方面,Spring Boot 4與GraalVM 24完全對齊,提前處理技術得到增強,這意味著更快的構建時間和更少的啟動內存占用。Spring Data引入了AOT存儲庫,將查詢方法轉換為與應用程序一起編譯的源代碼。
可觀察性方面,Spring Boot 4升級到Micrometer 2并集成了OpenTelemetry starter,使追蹤、日志和指標能夠無縫協作。SSL健康報告也得到了改進,證書鏈中即將過期的證書現在會在新的expiringChains條目中顯示,不再使用WILL_EXPIRE_SOON狀態,而是將即將過期的證書報告為VALID,這使得團隊在生產環境中監控SSL證書有效性變得更加容易。
模塊化是Spring Boot 4的另一個重要改進。新版本將自動配置和支持代碼拆分為更小、更專注的模塊,這意味著更快的構建和本地鏡像生成,更清晰的依賴管理,以及為Spring團隊和貢獻者提供了更好的可維護性。
對于使用starter依賴的開發者,不需要任何更改。例如,當需要JPA與Hibernate時,只需在pom.xml中添加以下依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
區別在于底層實現:JPA自動配置、Hibernate集成和驗證設置現在位于單獨的模塊中,這使得框架在運行時或AOT編譯期間處理配置時能夠更有選擇性。
新增的@ConfigurationPropertiesSource注解為更好的模塊化提供了支持。這個注解在構建時為spring-boot-configuration-processor提供提示,確保即使在跨模塊工作時也能生成完整的元數據。
Spring Framework 7的創新特性
Spring Framework 7帶來了許多期待已久的功能和精心設計的改進,涵蓋了測試、API設計和核心基礎設施等方面。
測試方面引入了測試上下文暫停功能。之前,長期運行的集成測試即使在空閑時也會消耗資源。現在,Spring可以暫停和恢復存儲在上下文緩存中的上下文,從而在大型測試套件中節省內存并加快測試執行速度。新的RestTestClient使得測試REST端點變得更加簡單,類似于WebTestClient,但不需要引入響應式基礎設施。
以下是一個使用RestTestClient的示例:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class HelloWorldApiIntegrationTest {
RestTestClient client;
@BeforeEach
void setUp(WebApplicationContext context) {
client = RestTestClient.bindToApplicationContext(context)
.build();
}
@Test
void shouldFetchHelloV1() {
client.get()
.uri("/api/v1/hello")
.exchange()
.expectStatus()
.isOk()
.expectHeader()
.contentTypeCompatibleWith(MediaType.TEXT_PLAIN)
.expectBody(String.class)
.consumeWith(message -> assertThat(message.getResponseBody()).containsIgnoringCase("hello"));
}
}
API版本化是其中一個最受期待的新功能。傳統上,開發者必須通過URL路徑約定、自定義頭或媒體類型來實現自己的解決方案。現在,框架提供了原生支持,開發者可以在控制器或方法級別指定版本屬性:
@RestController
@RequestMapping("/hello")
public class HelloWorldController {
@GetMapping(version = "1", produces = MediaType.TEXT_PLAIN_VALUE)
public String sayHelloV1() {
return "Hello World";
}
@GetMapping(version = "2", produces = MediaType.TEXT_PLAIN_VALUE)
public String sayHelloV2() {
return "Hi World";
}
}
也可以在控制器級別指定版本:
@RestController
@RequestMapping(path = "/hello", version = "3")
public class HelloWorldV3Controller {
@GetMapping(produces = MediaType.TEXT_PLAIN_VALUE)
public String sayHello() {
return "Hey World";
}
}
然后需要配置映射策略,可以是基于路徑的映射、基于查詢參數的映射、基于請求頭的映射或基于媒體類型頭的映射。以下配置使用基于路徑的映射:
@Configuration
public class ApiConfig implements WebMvcConfigurer {
@Override
public void configureApiVersioning(ApiVersionConfigurer configurer) {
configurer.usePathSegment(1);
}
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.addPathPrefix("/api/v{version}", HandlerTypePredicate.forAnnotation(RestController.class));
}
}
聲明式HTTP客戶端支持是另一個值得注意的特性。受Feign啟發但更輕量且完全集成,新的@HttpServiceClient注解使得創建HTTP客戶端變得更加簡單:
@HttpServiceClient("christmasJoy")
public interface ChristmasJoyClient {
@GetExchange("/greetings?random")
String getRandomGreeting();
}
然后需要激活類路徑掃描并配置客戶端分配到的服務組:
@Configuration
@Import(HttpClientConfig.HelloWorldClientHttpServiceRegistrar.class)
public class HttpClientConfig {
static class HelloWorldClientHttpServiceRegistrar extends AbstractClientHttpServiceRegistrar {
@Override
protected void registerHttpServices(GroupRegistry registry, AnnotationMetadata metadata) {
findAndRegisterHttpServiceClients(registry, List.of("com.baeldung.spring.mvc"));
}
}
@Bean
RestClientHttpServiceGroupConfigurer christmasJoyServiceGroupConfigurer() String baseUrl) {
return groups -> {
groups.filterByName("christmasJoy")
.forEachClient((group, clientBuilder) -> {
clientBuilder.baseUrl("https://christmasjoy.dev/api");
});
};
}
}
ChristmasJoyClient然后可以像往常一樣注入到其他Spring組件中:
@RestController
@RequestMapping(path = "/hello", version = "4")
@RequiredArgsConstructor
public class HelloWorldV4Controller {
private final ChristmasJoyClient christmasJoy;
@GetMapping(produces = MediaType.TEXT_PLAIN_VALUE)
public String sayHello() {
return this.christmasJoy.getRandomGreeting();
}
}
彈性注解現在內置在框架中。開發者可以用Spring注解來裝飾Spring組件方法,直接添加重試邏輯或并發限制:
@HttpServiceClient("christmasJoy")
public interface ChristmasJoyClient {
@GetExchange("/greetings?random")
@Retryable(maxAttempts = 3, delay = 100, multiplier = 2, maxDelay = 1000)
@ConcurrencyLimit(3)
String getRandomGreeting();
}
這些注解默認被忽略,除非在配置中添加@EnableResilientMethods。
多個TaskDecorator bean的支持消除了手動組合裝飾器的需要。例如,當有異步事件監聽器時:
@Component
@Slf4j
public class HelloWorldEventLogger {
@Async
@EventListener
void logHelloWorldEvent(HelloWorldEvent event) {
log.info("Hello World Event: {}", event.message());
}
}
可以簡單注冊兩個TaskDecorator bean:
@Configuration
@Slf4j
public class TaskDecoratorConfiguration {
@Bean
@Order(2)
TaskDecorator loggingTaskConfigurator() {
return runnable -> () -> {
log.info("Running Task: {}", runnable);
try {
runnable.run();
} finally {
log.info("Finished Task: {}", runnable);
}
};
}
@Bean
@Order(1)
TaskDecorator measuringTaskConfigurator() {
return runnable -> () -> {
final var ts1 = System.currentTimeMillis();
try {
runnable.run();
} finally {
final var ts2 = System.currentTimeMillis();
log.info("Finished within {}ms (Task: {})", ts2 - ts1, runnable);
}
};
}
}
空安全方面采用了JSpecify作為標準:
@Configuration
public class ApiConfig implements WebMvcConfigurer {
@Override
public void configureApiVersioning(@NonNull ApiVersionConfigurer configurer) {
configurer.usePathSegment(1);
}
}
棄用和移除的功能
隨著現代化進程,一些舊功能被清理:javax.*包被完全移除,只支持Jakarta EE 11;放棄了對Jackson 2.x的支持,Spring 7期望使用Jackson 3.x;移除了Spring JCL日志橋接,轉而采用Apache Commons Logging;棄用了JUnit 4支持,建議 exclusively 使用JUnit 5。如果仍然依賴這些較舊的API,遷移應該成為升級計劃的一部分。
這些更新使得應用程序更容易演進和強化,通過JSpecify空安全和Kotlin支持減少運行時錯誤,聲明式HTTP客戶端簡化了服務間調用,本地鏡像支持和可觀察性工具提高了云就緒程度。雖然重大升級總是需要投入測試工作,但在生產力、性能和可維護性方面的收益使得過渡是值得的。
https://www.jdon.com/81616-SpringBoot4-Spring7.html