Spring Boot 1.2/1.3でhot swapping的なこと

唐突にJavaの話。Spring Bootで変更を動的に反映する場合(いわゆるhot swappingとかhot deploy)はSpring Loadedを使えって出てくるのだけど、なんか動いたり動かなかったりしてなんでなんだろうと小一時間調べたメモ。Spring Boot + Maven + IntelliJ IDEA 15 on Mac 前提。

Spring Boot 1.2 with Spring Loaded

現行バージョンのSpring Boot 1.2では、Spring Loaded使えということになっている。

公式マニュアル通りにpom.xmlsrping-boot-maven-pluginにSpring Loadedへの依存を書くだけで CLIからmvnを叩いた場合 は普通に使える。

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>springloaded</artifactId>
            <version>1.2.4.RELEASE</version>
        </dependency>
    </dependencies>
</plugin>

IntelliJ IDEAでの罠

ただし、IntelliJから使う場合はいくつかの罠がある。

IntelliJではビルド実行/デバッグ実行中はauto compileが無効

IntelliJのSpring Bootビルド設定はpomを読んでくれない

  • pomにSpring Loadedの依存を書いても、IntelliJ組み込みのSpring Bootビルド設定から実行するとjavaagentの設定が有効にならない
    • VMオプションに-javaagent:<pathto>/springloaded.jar -noverifyを書けば動く
  • Spring BootビルドではなくMavenビルドからspring-boot:runで実行すればOK

つまり、Save and Makeマクロ書いてMavenビルドすればOK。Spring Loadedがちゃんと動くかはさておき。

Spring Boot 1.3 with devtools

次期バージョンのSpring Boot 1.3(現在RC1)からは、新規追加されるspring-boot-devtoolsを使うことでクラスパス上のファイルが更新された場合に自動的にアプリを再起動できるようになる。

再起動っていうと遅そうだけど、そこはトリックを使ってSpring Loadedほどではないが実用レベルに高速化している。仕組みとしては、まずクラスローダを2つ用意して、サードパーティライブラリ用クラスローダだと開発中のローカル用クラスローダに分ける。そして再起動時は後者のみを破棄して新規に作り直すことで、変化しないサードパーティライブラリの大量のクラスを読みなおすことを抑止して高速化しているとのこと。つまり巨大モノリシックなアプリ以外ならそこそこ速いのではないか。

設定は例によってpomを書くだけ。

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

devtoolsにはこのauto restartの他にも、ブラウザ拡張のLive reloadに対応、テンプレートのキャッシュを開発時は自動で無効化など、デフォルトで開発が楽になる仕組みが入っていて便利。

IntelliJのSpring Bootビルド設定でもdevtoolsは有効だった。ただしIntelliJでは相変わらず自動コンパイルはできない(仕様)ので、前述のマクロは必要。

JavaのHot swappingって昔から信用できない印象があるので(なぜか挙動が微妙なので結局アプリ再起動しよう、みたいな)、ちょっともたつくけどdevtoolsの再起動方式のが好みかな。


追記

期待し過ぎないように@makingさんのコメントを追記しておきます。