Spring Boot 3.2.5 New Features: Multithreaded Bean Init, @Fallback, RestClient & More
This article walks through Spring Boot 3.2.5 enhancements including multithreaded bean initialization, the new @Fallback annotation, handling duplicate bean names, RestClient.create(URI) usage, header binding to records, expanded task‑scheduler metadata, and a host of other backend improvements.
1. Multithreaded Bean Initialization
Since Spring Framework 6.2, singleton beans can be instantiated concurrently using CompletableFuture.runAsync . Define a custom executor bean named bootstrapExecutor to control the thread pool.
<code>@Bean
public Executor bootstrapExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(5);
taskExecutor.setMaxPoolSize(5);
taskExecutor.initialize();
return taskExecutor;
}
</code>2. New @Fallback Annotation
The @Fallback annotation acts as an alternative to @Primary when multiple beans of the same type exist. It marks a bean as a fallback candidate, selected only if no primary bean matches.
<code>interface CommonDAO {}
class UserDAO implements CommonDAO {}
class PersonDAO implements CommonDAO {}
@Configuration
public class AppConfig {
@Bean
public UserDAO userDAO() {
return new UserDAO();
}
@Bean
@Fallback
public PersonDAO personDAO() {
return new PersonDAO();
}
@Bean
public CommonService commonService(CommonDAO dao) {
return new CommonService(dao);
}
}
</code>In this example, CommonService receives UserDAO unless it is absent, in which case PersonDAO (marked with @Fallback ) is injected.
3. Defining Two Beans with the Same Name
Spring 6.2 now allows beans with identical names; the later definition overrides the earlier one.
<code>@Configuration
public class AppConfig {
@Bean(name = "a")
Person personA() {
return new Person(1);
}
@Bean(name = "a")
Person personB() {
return new Person(2);
}
}
</code>4. RestClient Improvements
The RestClient API adds a create(URI) overload that parses the supplied URI as the base URL, simplifying client calls.
<code>@GetMapping("/client")
public String client() {
return RestClient.create("http://localhost:8080")
.get()
.uri(URI.create("/params/index"))
.retrieve()
.body(String.class);
}
</code>5. Binding Header Data to Records
From Spring 6.2 onward, @RequestHeader values can be bound directly to fields of a record , enabling concise parameter objects.
<code>@GetMapping("/{path}")
public void get(Params params, @PathVariable long path,
@RequestParam String foo, @RequestHeader String accept) {
System.out.printf("path: %d%n", path);
System.out.printf("foo: %s%n", foo);
System.out.printf("accept: %s%n", accept);
System.out.printf("params: %s%n", params);
}
public static record Params(@PathVariable long path,
@RequestParam String foo,
@RequestHeader String accept) {}
</code>6. Task Scheduler New Metadata
The /actuator/scheduledtasks endpoint now reports additional fields for each scheduled task:
Last execution time
Last execution status
Next execution time
7. Other Backend Improvements
Updated UndertowHttpHandlerAdapter for scheduling.
Enhanced Javadoc for @Contract with new return‑value information.
AOT now ignores cascading and container‑element constraints during bean validation.
Lazy‑proxy bean resolution avoids duplicate singleton parsing.
Introduced @DisabledInAotMode with custom reasons.
Optimized ResponseBodyEmitter with optimistic locking.
Improved Cookie support in WebClient and WebTestClient .
Added @CheckReturnValue annotation.
Virtual‑thread friendly options for ThreadPoolTaskExecutor and ThreadPoolTaskScheduler .
Various refactorings and bug fixes across the Spring ecosystem.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.