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:

None

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

None

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:

None

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:

None

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:

None

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.