{"id":660362,"date":"2025-11-20T21:11:35","date_gmt":"2025-11-20T20:11:35","guid":{"rendered":"https:\/\/blog.jetbrains.com\/?post_type=idea&#038;p=660362"},"modified":"2026-01-30T10:42:09","modified_gmt":"2026-01-30T09:42:09","slug":"spring-boot-4","status":"publish","type":"idea","link":"https:\/\/blog.jetbrains.com\/ja\/idea\/2025\/11\/spring-boot-4","title":{"rendered":"Spring Boot 4: Leaner, Safer Apps and a New Kotlin Baseline"},"content":{"rendered":"\n<p>Spring Boot 4.0 has officially landed. At JetBrains, we\u2019ve been tracking the updates since the first milestones to ensure that IntelliJ IDEA delivers a smooth and reliable development experience.<\/p>\n\n\n\n<p>While many of the core capabilities come directly from Spring Framework 7, Spring Boot remains the adoption enabler that brings everything together: sensible defaults, consistent configuration, unified starters, and the familiar lightning-fast productivity when creating applications.<\/p>\n\n\n\n<p>As the most popular framework in the Java world, Spring Boot also helps developers move from older JDK versions to newer ones that offer better performance, more efficient garbage collectors, and modern language features.<\/p>\n\n\n\n<p>This major Spring Boot release introduces cleaner modularization to reduce memory usage, improved observability with Micrometer, JSpecify as the standard null-safety library, and many other small improvements that streamline daily development.<\/p>\n\n\n\n<p>For JetBrains, the biggest news in Spring Boot 4 is that Kotlin 2.2 is now the official baseline version for the framework. This milestone is the result of a <a href=\"https:\/\/blog.jetbrains.com\/kotlin\/2025\/05\/strategic-partnership-with-spring\/\">long-standing collaboration<\/a> between the JetBrains Kotlin team and the Spring Framework team.<\/p>\n\n\n\n<p>Let\u2019s take a closer look at Spring Boot 4\u2019s new features through the lens of Kotlin 2.2.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Nullability<\/h2>\n\n\n\n<p>The Kotlin compiler and IntelliJ IDEA now support JSpecify annotations natively. You will receive a compiler warning if you use JSpecify-annotated Java code incorrectly. In addition, IntelliJ IDEA will warn you if you try to assign a Java variable annotated with <code>@Nullable<\/code> to a non-nullable variable in Kotlin, and vice versa.&nbsp;<\/p>\n\n\n\n<p>For example, for the Java interface:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\">@NullMarked\n\npublic interface QuoteProvider {\n\n&nbsp;&nbsp;&nbsp;&nbsp;Quote findQuote(String text);\n\n}<\/pre>\n\n\n\n<p>A Kotlin implementation must return a non-nullable Quote object from the overridden <code>findQuote()<\/code> method:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"1124\" height=\"288\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/11\/image1-2.png\" alt=\"\" class=\"wp-image-660388\"\/><\/figure>\n\n\n\n<p>You\u2019ll see the following error message:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"1600\" height=\"516\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/11\/image-35.png\" alt=\"\" class=\"wp-image-660366\"\/><\/figure>\n\n\n\n<p>IntelliJ IDEA detects the issue and suggests changing the return type to non-nullable. JSpecify is now the default library for nullability checks across all Spring projects. This means that when you create a Spring Boot 4 project in Kotlin, you can be sure that the framework types that you use are null-aware.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">API versioning<\/h2>\n\n\n\n<p>API versioning in Kotlin works much the same way as in <a href=\"https:\/\/blog.jetbrains.com\/idea\/2025\/11\/intellij-idea-2025-3-spring-7\/#rest-api-versioning\">Java<\/a>. Thanks to Spring\u2019s well-designed API versioning mechanism, adding a version takes only a few lines of configuration and a single annotation attribute. In Kotlin, the versioned API looks just as straightforward:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\">@RestController\n\n@RequestMapping(&quot;\/api&quot;, produces = &#091;MediaType.APPLICATION_JSON_VALUE])\n\nclass QuoteController(private val klient: QuoteKlient) {\n\n&nbsp;&nbsp;&nbsp;&nbsp;@GetMapping(&quot;quote&quot;, version = &quot;1.0&quot;)\n\n&nbsp;&nbsp;&nbsp;&nbsp;fun fetchRandomQuote(): ResponseEntity&lt;Quote&gt; = \nResponseEntity.ok(klient.fetchRandomQuote())\n\n&nbsp;&nbsp;&nbsp;&nbsp;@GetMapping(&quot;quote&quot;, version = &quot;2.0&quot;)\n\n&nbsp;&nbsp;&nbsp;&nbsp;fun fetchRandomQuotes(): ResponseEntity&lt;List&lt;Quote&gt;&gt; = \nResponseEntity.ok(klient.fetchRandomQuotes())\n\n}<\/pre>\n\n\n\n<p>There\u2019s nothing fancy here, just the usual Kotlin conciseness, with IntelliJ IDEA inspections helping you configure and validate version formats.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Bean registration<\/h3>\n\n\n\n<p>Bean registration is one of the areas where Kotlin truly shines. Thanks to its expressiveness and extensibility, it provides a powerful DSL for registering beans dynamically when the regular <code>@ConditionalOn\u2026<\/code> annotation family is <a href=\"https:\/\/blog.jetbrains.com\/idea\/2025\/11\/intellij-idea-2025-3-spring-7\/#dynamic-bean-registration\">insufficient<\/a>.<\/p>\n\n\n\n<p>For example, instead of the following Java code:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\">public class QuoteProviderRegistrar implements BeanRegistrar {\n    @Override\n\n&nbsp;&nbsp;&nbsp;&nbsp;public void register(BeanRegistry registry, Environment env) {\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;registry.registerBean(&quot;quoteProviderDb&quot;, QuoteProviderDb.class);\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;registry.registerBean(&quot;quoteProviderFallback&quot;,\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;QuoteProviderFallback.class,\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;spec -&gt; {\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;spec.fallback();\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;spec.order(1);\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);\n\n&nbsp;&nbsp;&nbsp;&nbsp;}\n\n}<\/pre>\n\n\n\n<p>You can write a more elegant version without all the <code>.class<\/code> calls and lambda boilerplate:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\">class KuoteProviderRegistrar : BeanRegistrarDsl({\n\n&nbsp;&nbsp;&nbsp;&nbsp;registerBean&lt;QuoteProviderDb&gt;(&quot;quoteProviderDb&quot;)\n\n&nbsp;&nbsp;&nbsp;&nbsp;registerBean&lt;QuoteProviderFallback&gt;(\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;name = &quot;quoteProviderFallback&quot;,\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fallback = true,\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;order = 1\n\n&nbsp;&nbsp;&nbsp;&nbsp;)\n\n})<\/pre>\n\n\n\n<p>Much cleaner, right?&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Conclusion<\/h3>\n\n\n\n<p>Spring Boot is the most popular framework for Java development \u2013 and for good reason. With Spring Boot 4 establishing Kotlin 2.2 as the baseline and offering first-class support, we expect to see even broader Kotlin adoption among backend developers who want to use the latest language features.&nbsp;<\/p>\n\n\n\n<p>You can try Spring Boot 4 in the <a href=\"https:\/\/www.jetbrains.com\/idea\/nextversion\/\" target=\"_blank\" rel=\"noopener\">2025.3 Beta<\/a> release or wait for the stable version, which is expected in early December.<\/p>\n\n\n\n<p>At JetBrains, we continue to work closely with the Spring Framework team to ensure Kotlin remains well-integrated and fully supported in the Spring ecosystem.<\/p>\n","protected":false},"author":1511,"featured_media":660557,"comment_status":"closed","ping_status":"closed","template":"","categories":[89],"tags":[3211,8968],"cross-post-tag":[],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/idea\/660362"}],"collection":[{"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/idea"}],"about":[{"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/types\/idea"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/users\/1511"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/comments?post=660362"}],"version-history":[{"count":9,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/idea\/660362\/revisions"}],"predecessor-version":[{"id":677554,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/idea\/660362\/revisions\/677554"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/media\/660557"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/media?parent=660362"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/categories?post=660362"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/tags?post=660362"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/cross-post-tag?post=660362"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}