My article is open to everyone; non-member readers can click this link to read the full text.
Have you all noticed recently? When we create a new Spring Boot project, there is now an option for the Spring Boot 4.0.0 preview, as shown in the image below:

And Spring Boot 4 is built on the all-new Spring Framework 7.0.0, as shown in the image below:

So, here comes the question: what are the important changes in the new version? Next, let me give you a sneak peek.
1. Elegant Version Control
The new version introduces elegant support for API versioning, allowing developers to implement version control through the version
parameter in the @RequestMapping
annotation, as shown in the code below:
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class VersionedController {
@RequestMapping(value = "/user", version = "1")
public String getUserV1() {
// Version 1 implementation
System.out.println("Version 1");
return "Version 1";
}
@RequestMapping(value = "/user", version = "2")
public String getUserV2() {
// Version 2 implementation
System.out.println("Version 2");
return "Version 2";
}
}
Program execution effect:

2. Convenient Bean Injection
The new version introduces a new BeanRegistrar
contract, which allows for more flexible Bean registration (registering multiple Beans at once). The sample code is as follows:
import org.springframework.beans.factory.BeanRegistrar;
import org.springframework.beans.factory.BeanRegistry;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.env.Environment;
@Configuration
@Import(MyBeansRegistrar.class)
public class MyConfiguration {
}
class MyBeansRegistrar implements BeanRegistrar {
@Override
public void register(BeanRegistry registry,
Environment env) {
registry.registerBean("user", User.class);
if (env.matchesProfiles("dev")) {
registry.registerBean(Order.class, spec -> spec
.supplier(context -> new Order("order_001")));
}
}
}
class User {
private String name;
}
class Order {
public Order(String name) {
this.name = name;
}
private String name;
}
Write a unit test to prove that the registered Beans can be used normally:

3. Null-Safety Improvements
The new version adopts JSpecify annotations to declare the null-safety of its API, using @Nullable
to indicate that a value can be null and @NonNull
to indicate it cannot. This works in conjunction with IntelliJ IDEA to provide warnings or error messages, as in the following code:
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
public class Person {
private String name;
public void setName(@NonNull String name) {
this.name = name;
}
@Nullable
public String getName() {
return this.name;
}
}
The warning message is also visible in IntelliJ IDEA:

The display format varies between different IDEA versions; the author is using IDEA 2024, as newer versions are required to support the new features.
4. Easy Creation of HTTP Proxies
The new version provides the @ImportHttpServices
annotation, making it easier to create proxies for HTTP interfaces. The sample code is below (it allows you to easily declare, detect, and configure entire groups of HTTP services):
@Configuration(proxyBeanMethods = false)
@ImportHttpServices(group = "weather", types = {FreeWeather.class, CommercialWeather.class})
@ImportHttpServices(group = "user", types = {UserServiceInternal.class, UserServiceOfficial.class})
static class HttpServicesConfiguration extends AbstractHttpServiceRegistrar {
@Bean
public RestClientHttpServiceGroupConfigurer groupConfigurer() {
return groups -> groups.filterByName("weather", "user")
.configureClient((group, builder) -> builder.defaultHeader("User-Agent", "My-Application"));
}
}
5. Other Seven Changes
Other upgraded features include:
- SPEL Expression Upgrade: SPEL expressions now support null-safety and the Elvis operator, as shown in the following code:
@Value("#{systemProperties['pop3.port'] ?: 25}")
This injects the value of the pop3.port
system property, or injects the value 25
if the property is not defined.
- GraalVM Native Application Support: With Spring AOT technology, applications can be compiled into native images, significantly reducing startup times.
- Support for Jackson 3.x: Support for Jackson 2.x has been dropped and upgraded to Jackson 3.x.
- Servlet and WebSocket Version Upgrade: It uses Servlet 6.1 and WebSocket 2.2 as the underlying implementation for web applications. This means applications should be deployed on the latest Servlet containers, such as Tomcat 11+ and Jetty 12.1+.
- HttpHeaders Optimization:
HttpHeaders
operations are as follows:
@RestController
public class MyController {
@GetMapping("/headers")
public ResponseEntity<String> handleRequest(HttpHeaders headers) {
// Old way (deprecated)
// headers.getFirst("X-Custom-Header");
// New way
String value = headers.firstValue("X-Custom-Header").orElse(null);
// Iterate over all headers
headers.forEach((name, values) -> {
System.out.println(name + ": " + values);
});
return ResponseEntity.ok("Processed");
}
}
- Feature Removals:
The following have been removed in the new version:
1. The XML configuration namespace for Spring MVC is now deprecated in favor of Java configuration.
2. JUnit 4 support within the Spring TestContext Framework is now deprecated.
3. Jackson 2.x support is deprecated in favor of Jackson 3.x.
4. Spring JCL has been discontinued.
- Increased Minimum Environment Requirements:
Jakarta EE 11 (Tomcat 11+)
Kotlin 2.x
JSONassert 2.0
GraalVM 23
For more upgrade information, refer to the official website:
https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-7.0-Release-Notes...
Summary
Programming is a profession of lifelong learning. Changes in frameworks and tools mean we get more convenient and user-friendly methods, which is beneficial for developers.
So, let's learn, use, and experiment with them together.