0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SpringBoot 3.5 to 4.0 メモ

Last updated at Posted at 2025-11-23

概要

SpringBoot 4.0がGAとなりました!
Release Notesを参考に3.5系からの変更点をまとめます。

自分が移行するときに関係のあるものや興味があるものが中心となりますがご容赦ください🙇‍♂️

⚙️ 移行関連 ⚙️

Gradle version

  • before: Gradle 8.x (8.4 or later)
  • after: Gradle 8.x (8.14 or later) or 9.x

gradle 8.14未満を利用している場合は version upが必要です。
SpringBoot 4へ上げる前にversion upしておきましょう!

# 非推奨な設定がないか確認
./gradlew --warning-mode=all
# version up
./gradlew wrapper --gradle-version 9.2.0
# 非推奨な設定がないか確認(任意)
./gradlew --warning-mode=all

ライブラリの整理

SpringBoot4ではアプリケーションjarの軽量化のために、moduleの細分化が行われています。

例えば spring-boot-starter-webmvcから

  • test関連が spring-boot-starter-webmvc-test
  • RestClientあたりのclient関連が spring-boot-starter-restclient, spring-boot-starter-restclient-test

なのでClassが見つからない系のエラーが発生したらModule Dependenciesを参考にライブラリを追加しましょう。

Jackson 2 to 3

いくつかデフォルトの設定値が変更されているようです。

特に影響が大そうなのは、

  • DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS のデフォルト false
    • タイムスタンプで出力されていた値が、YYYY-MM-DD...のような形式になるかも
  • MapperFeature.SORT_PROPERTIES_ALPHABETICALLY のデフォルト true
    • 定義順ではなく、アルファベット順の出力になるかも(RestControllerの出力には影響なし...?)

の2つとのこと。

json形式のread / writeがある場合にはmigrationの前後で互換性があるか確認した方が良さそうです…!

まずい例:DBにjsonで書き込んでいた。DATE型の扱いの変更で、migration前にwriteした値をmigration後にreadできなくなった😱

Dependency Management for Spring Retry

spring-retryがspring-coreに吸収されたため、依存の指定がいらなくなくなりました

- implementation('org.springframework.retry:spring-retry')

Retry機能を有効にするアノテーションも変更になっています。

-import org.springframework.retry.annotation.EnableRetry;
-@EnableRetry
+import org.springframework.resilience.annotation.EnableResilientMethods;
+@EnableResilientMethods

アノテーションでのリトライ定義も少し変わりました

サンプル
// 直接指定
@Retryable(
        delay = 10,
        maxAttempts = 5
)
// プロパティを指定
@Retryable(
        delayString = "${hoge.delay}",
        maxAttemptsString = "${hoge.max-attempts}"
)

Liveness and Readiness Probes

デフォルトで有効になるとのこと
→ management port設定していない場合はoffにしておいた方がいいかも

HttpMessageConverters deprecation

TODO 移行方法

Testcontainers 2.0

ライブラリのrenameが必要です。

各ライブラリに prefix testcontainers- を付与する必要があります。

-   testImplementation("org.testcontainers:kafka")
+   testImplementation("org.testcontainers:testcontainers-kafka")

Spring Batch 6.0

その他

EnvironmentPostProcessor

-import org.springframework.boot.env.EnvironmentPostProcessor
+import org.springframework.boot.EnvironmentPostProcessor

RestTemplateBuilder

// dependency
+org.springframework.boot:spring-boot-starter-restclient

// class
-import org.springframework.boot.web.client.RestTemplateBuilder;
+import org.springframework.boot.restclient.RestTemplateBuilder;

🚀 新機能 🚀

RestTestClient

WebTestClientのRestClient版です!
使い勝手は似てそう!

build.gradle
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-webmvc'
+   testImplementation 'org.springframework.boot:spring-boot-resttestclient'
}
@SpringBootTest
@AutoConfigureRestTestClient // 忘れずに!
class SampleControllerTest {
    @Autowired
    RestTestClient restTestClient;

    @Test
    void test() {
        restTestClient.get()
                .uri("/sample")
                .exchange()
                .expectStatus().isOk()
                .expectBody().json(
                        // language=json
                        """
                        {
                          "message":"this is sample api.",
                        }
                        """
                );
    }
}

@ConcurrencyLimit

@ConcurrencyLimitを使うことで簡単に同時処理数の制限をかけられるようになりました!

動作確認可能なサンプルコードです!

@EnableResilientMethods // 機能を有効にするために必要。@Configurationなクラスにつける
@Configuration
class ConcurrencyLimitConfiguration {
    @Bean
    fun runner(sampleTask: SampleTask) = CommandLineRunner { _ ->
        Executors.newVirtualThreadPerTaskExecutor().use { executor ->
            repeat(10) {
                executor.execute {
                    sampleTask.run()
                }
            }
        }
    }

    @Bean
    fun sampleTask() = SampleTask()

    open class SampleTask {
        @ConcurrencyLimit(5) // 引数に同時処理可能数
        open fun run() {
            println("task start")
            TimeUnit.SECONDS.sleep(1)
            println("task end")
        }
    }
}

アノテーションがないと、"task start" が10回出力された後に "task end"も10回出力されますが、
アノテーションがあると、"task start" が5回出力された後待ちが発生してくれます!

接続数の管理はインメモリとなっています。
「接続数を共有したい場合は?」と一瞬思ったのですが、
複数起動したプロセス全体のratelimit的な使い方というよりも
Virtual Threadを起動しすぎないようにとかプロセス単体でリソースを使いすぎないように制御するために登場した機能っぽそうでした。

サードパーティライブラリ

SpringBootと互換性のあるバージョンをまとめておきます

ライブラリ Version
spring-doc 3.0.0
mybatis-springboot-starter ※Issue

その他参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?