Spring Boot 3.0: Was sich ändert und wie die Migration gelingt
Das nächste Major-Release ist da
Am 24. November 2022 hat VMware Spring Boot 3.0 als GA veröffentlicht -- das erste Major-Release seit dem Erscheinen von Spring Boot 2.0 im März 2018. Über vier Jahre lagen dazwischen, und die Änderungen sind entsprechend umfangreich. Spring Boot 3.0 ist nicht einfach ein inkrementelles Update, sondern ein Plattformwechsel: Neues Framework, neue Baseline, neuer Namespace.
Wir bei encircle360 haben in den vergangenen Tagen unsere ersten Services evaluiert und mit der Migration begonnen. Hier ist unsere Übersicht über die wichtigsten Änderungen -- und die praktischen Schritte, die wir für eine erfolgreiche Migration empfehlen.
Java 17 als Mindestanforderung
Die wohl grundlegendste Entscheidung: Spring Boot 3.0 setzt Java 17 als Minimum voraus. Kein Java 11, kein Java 8 -- wer noch nicht auf Java 17 migriert hat, muss das jetzt nachholen. Wie wir in unserem Java-17-Artikel beschrieben haben, bringt Java 17 mit Records, Sealed Classes und Pattern Matching erhebliche Verbesserungen. Dass Spring jetzt diese Version als Baseline definiert, ist ein Signal an das gesamte Ökosystem: Java 17 ist die neue Referenz für Enterprise-Java.
Für Teams, die diesen Schritt bereits vollzogen haben, ist das kein Hindernis. Für alle anderen empfehlen wir dringend, die Java-17-Migration als separaten Schritt vor dem Spring-Boot-Upgrade durchzuführen -- nicht beides gleichzeitig.
Von javax zu jakarta: Der größte Breaking Change
Die Umstellung von javax.* auf jakarta.* ist der Einzelpunkt, der bei der Migration den meisten mechanischen Aufwand verursacht. Spring Boot 3.0 basiert auf Jakarta EE 9+ und damit auf dem neuen Namespace, den die Eclipse Foundation nach der Übernahme von Java EE eingeführt hat.
Konkret bedeutet das: Jeder Import, der bisher mit javax. begann, muss auf jakarta. umgestellt werden.
// Vorher (Spring Boot 2.x)
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.validation.constraints.NotNull;
import javax.servlet.http.HttpServletRequest;
// Nachher (Spring Boot 3.0)
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.validation.constraints.NotNull;
import jakarta.servlet.http.HttpServletRequest;
Das betrifft nicht nur den eigenen Code, sondern auch Drittanbieter-Bibliotheken. Jede Bibliothek, die javax.persistence, javax.validation, javax.servlet oder andere Java-EE-APIs nutzt, muss in einer Jakarta-kompatiblen Version vorliegen. Hibernate 6.1, Jakarta Validation 3.0, Tomcat 10.1 -- Spring Boot 3.0 bringt diese Versionen mit, aber eigene Abhängigkeiten muss man selbst prüfen.
In den meisten IDEs lässt sich die Namespace-Umstellung über ein globales Suchen-und-Ersetzen erledigen. IntelliJ bietet dafür sogar eine dedizierte Migration-Funktion. Der mechanische Aufwand ist hoch, aber intellektuell überschaubar.
Spring Framework 6 unter der Haube
Spring Boot 3.0 baut auf Spring Framework 6.0 auf -- dem ersten Major-Release des Kern-Frameworks seit 2017. Neben der Jakarta-EE-Umstellung bringt Spring Framework 6 eine überarbeitete Architektur mit, die stärker auf AOT-Verarbeitung (Ahead-of-Time) ausgerichtet ist. Das wirkt sich vor allem auf die GraalVM-Unterstützung aus, auf die wir gleich eingehen.
Für den Entwickleralltag ändert sich am Programmiermodell wenig. Controller, Services, Repositories -- die bekannten Annotationen und Muster funktionieren wie gewohnt. Die Änderungen liegen eher in den Interna, die man als Anwendungsentwickler selten direkt berührt.
Security-Konfiguration: Abschied vom WebSecurityConfigurerAdapter
Eine Änderung, die viele Projekte betrifft: Der WebSecurityConfigurerAdapter wurde entfernt. Wer seine Security-Konfiguration bisher durch das Erweitern dieser Klasse definiert hat, muss auf das neue komponentenbasierte Modell mit SecurityFilterChain-Beans umstellen.
// Vorher (Spring Boot 2.x) -- veraltet und in 3.0 entfernt
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/api/public/**").permitAll()
.anyRequest().authenticated()
.and()
.oauth2ResourceServer().jwt();
}
}
// Nachher (Spring Boot 3.0) -- komponentenbasiert
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/public/**").permitAll()
.anyRequest().authenticated()
)
.oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()));
return http.build();
}
}
Neben dem Wegfall des Adapters fällt auf: antMatchers() wurde durch requestMatchers() ersetzt und die Lambda-basierte DSL ist jetzt der bevorzugte Konfigurationsstil. Die alte Method-Chaining-Syntax mit .and() wird als deprecated markiert.
GraalVM Native Image: Endlich erstklassiger Support
In unserem GraalVM-Artikel hatten wir 2020 noch geschrieben, dass Native Image für Spring-Boot-Anwendungen keine realistische Option sei. Das ändert sich mit Spring Boot 3.0 grundlegend. Die Integration von GraalVM Native Image ist keine experimentelle Erweiterung mehr, sondern ein offiziell unterstütztes Feature.
Spring Boot 3.0 bringt eine AOT-Engine mit, die zur Build-Zeit den Application Context analysiert und den nötigen Code generiert, um Reflection und dynamische Proxies zu vermeiden. Damit entfallen die mühsamen manuellen Konfigurationsdateien, die bisher nötig waren.
Für eigene Beans, die zur Laufzeit Reflection benötigen, können AOT-Hints registriert werden:
@Configuration
@ImportRuntimeHints(MyRuntimeHints.class)
public class AppConfig {
}
public class MyRuntimeHints implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
hints.reflection()
.registerType(MyDto.class, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
MemberCategory.INVOKE_DECLARED_METHODS);
hints.resources()
.registerPattern("templates/*.html");
}
}
Das Maven- und Gradle-Plugin unterstützen den Native-Build direkt. Für Maven reicht ein Profil:
mvn -Pnative native:compile
Die Startzeiten sinken auf Millisekunden, der Speicherverbrauch fällt drastisch. Für Microservices in Kubernetes-Umgebungen und Serverless-Szenarien ist das ein echter Durchbruch -- und eine direkte Antwort auf Quarkus und Micronaut, die diesen Vorteil bisher exklusiv hatten.
Observability mit Micrometer
Spring Boot 3.0 führt ein neues Observability-Konzept ein, das auf der Micrometer Observation API basiert. Statt Metriken und Traces separat zu instrumentieren, gibt es jetzt eine einheitliche Abstraktion: Eine Observation erzeugt automatisch sowohl Metriken als auch Trace-Spans.
Das Spring-Framework selbst ist bereits umfassend instrumentiert. HTTP-Requests, RestTemplate-Aufrufe, JDBC-Queries -- all das generiert automatisch Observations, die an Prometheus, Zipkin, Wavefront oder andere Backends weitergeleitet werden können. Wer bisher manuell Micrometer-Timer und Brave-Spans verdrahtet hat, kann sich über deutlich weniger Boilerplate freuen.
HttpClient 5 und weitere Breaking Changes
Apache HttpClient 4 wird nicht mehr unterstützt. Wer httpclient als Dependency eingebunden hat, muss auf httpclient5 wechseln. Das betrifft vor allem Projekte, die den Apache HttpClient direkt nutzen oder über RestTemplate konfigurieren.
Eine weitere Vereinfachung betrifft @ConfigurationProperties: Die Annotation @ConstructorBinding ist bei Klassen mit nur einem Konstruktor nicht mehr nötig. Spring Boot erkennt automatisch, dass Constructor Binding gewünscht ist. Bei mehreren Konstruktoren muss die Annotation weiterhin den gewünschten Konstruktor markieren.
// Vorher (Spring Boot 2.x) -- @ConstructorBinding erforderlich
@ConfigurationProperties(prefix = "app")
@ConstructorBinding
public record AppProperties(String name, int port) {}
// Nachher (Spring Boot 3.0) -- Annotation entfällt bei einem Konstruktor
@ConfigurationProperties(prefix = "app")
public record AppProperties(String name, int port) {}
Zusätzlich wurden zahlreiche APIs entfernt, die in Spring Boot 2.x als deprecated markiert waren. Wer die Deprecation-Warnungen in der 2.7.x-Linie ernst genommen hat, ist hier im Vorteil.
Unser Migrationsfahrplan
Nach den ersten Erfahrungen mit der Migration empfehlen wir folgenden Stufenplan:
- Zuerst auf Spring Boot 2.7.x aktualisieren -- die letzte 2.x-Version enthält Kompatibilitäts-Layer und Deprecation-Hinweise, die den Übergang erleichtern.
- Java 17 sicherstellen -- falls noch nicht geschehen, ist das die Voraussetzung.
- javax-zu-jakarta-Migration durchführen -- ein globales Suchen-und-Ersetzen, gefolgt von sorgfältigem Testen.
- Security-Konfiguration umstellen -- WebSecurityConfigurerAdapter durch SecurityFilterChain-Beans ersetzen.
- Drittanbieter-Bibliotheken prüfen -- insbesondere auf Jakarta-Kompatibilität und HttpClient 5.
- Deprecation-Warnungen bereinigen -- alles, was in 2.7 als deprecated markiert ist, wird in 3.0 fehlen.
- Spring Boot 3.0 einbinden und Tests laufen lassen -- die verbleibenden Probleme zeigen sich hier.
Wir rechnen mit zwei bis vier Tagen pro Service, abhängig von der Komplexität und der Anzahl der Drittanbieter-Abhängigkeiten. Die javax-zu-jakarta-Umstellung ist dabei der zeitaufwändigste Einzelpunkt, weil sie sich durch alle Schichten zieht.
Unser Fazit
Spring Boot 3.0 ist das bedeutendste Release seit der 2.0-Linie. Die Migration ist kein triviales Upgrade, aber der Aufwand ist gut investiert: Java 17 als Basis, erstklassiger GraalVM-Support und ein modernes Observability-Konzept positionieren Spring Boot für die nächsten Jahre.
Besonders der Native-Image-Support ist ein Meilenstein. Was vor zwei Jahren noch als experimentell galt, ist jetzt produktionsreif. Damit steht Spring Boot in Sachen Startzeit und Speicherverbrauch endlich auf einer Stufe mit Quarkus und Micronaut -- bei voller Kompatibilität mit dem bestehenden Ökosystem.
Spring Boot 2.7 wird noch bis November 2023 mit Sicherheitsupdates versorgt. Die Migration eilt also nicht, aber die Planung sollte jetzt beginnen. Wer bereits auf Java 17 läuft, hat die größte Hürde bereits genommen.
Geschrieben von
Patrick HütterGründer & Software-Architekt
Softwarearchitekt, Ingenieur und Unternehmer. Patrick baut seit über einem Jahrzehnt Produkte und Plattformen — von Enterprise-Backends über Cloud-Native-Infrastruktur bis hin zu KI-gestützten Anwendungen. Als Gründer von encircle360 verbindet er technische Tiefe mit unternehmerischem Denken und treibt Open-Source-Projekte voran, die echten Impact haben.
Das könnte dich auch interessieren
Vom Manifest zur Produktion: Wie ADL, A2A und das Inference Gateway die Agenten-Infrastruktur revolutionieren
05.07.2026 · 12 Min. Lesezeit
Agent-Orchestrierung mit Java: Wie Sie LLM-Agenten produktionsreif in die JVM bringen
04.07.2026 · 6 Min. Lesezeit
Spring AI: Wie Java-Entwickler endlich KI-Features ohne Umwege integrieren
25.03.2026 · 5 Min. Lesezeit