Dev Study
← 解説「スターターと BOM」に戻る

サンプルコードで身につける: スターターと BOM

解説で学んだ概念を、5つの具体例で確認します。素朴な例から実務寄りの例へと進みます。

1スターターの JAR を開ける

spring-boot-starter-webmvc-4.1.1.jar(4749 バイト)の中身です。入っているのはとライセンス文書だけで、 は1つもありません。このプロジェクトのにあった6つはどれも同じで、 0 個・4.7KB 台でした。

$ unzip -l spring-boot-starter-webmvc-4.1.1.jarコマンド出力
Length Date Time Name
--------- ---------- ----- ----
0 02-01-1980 00:00 META-INF/
252 02-01-1980 00:00 META-INF/MANIFEST.MF
11359 02-01-1980 00:00 META-INF/LICENSE.txt
210 02-01-1980 00:00 META-INF/NOTICE.txt
--------- -------
11821 4 files

2スターターの実体は pom の依存宣言

同じスターターの (spring-boot-starter-webmvc-4.1.1.pom)の依存部分です。5つの依存が並んでいるだけで、これがスターターの中身のすべてです。うち3つはまた別のスターターで、 はその pom もたどっていきます。

spring-boot-starter-webmvc-4.1.1.pom の <dependencies>設定ファイル
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>4.1.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jackson</artifactId>
<version>4.1.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>4.1.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-http-converter</artifactId>
<version>4.1.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-webmvc</artifactId>
<version>4.1.1</version>
<scope>compile</scope>
</dependency>
</dependencies>

31行の依存をたどった結果

自分の pom に実行時の依存として書いたのは、2行目の spring-boot-starter-webmvc だけです。そこから 、、ログの部品、 7.0.9 の各へと枝が伸びています。長いので途中までの抜粋で、実行時クラスパスに並んだ は全部で 39 個でした。

$ mvn dependency:tree(test スコープの行を除いたもの。抜粋)コマンド出力
[INFO] com.example:web:jar:0.0.1-SNAPSHOT
[INFO] +- org.springframework.boot:spring-boot-starter-webmvc:jar:4.1.1:compile
[INFO] | +- org.springframework.boot:spring-boot-starter:jar:4.1.1:compile
[INFO] | | +- org.springframework.boot:spring-boot-starter-logging:jar:4.1.1:compile
[INFO] | | | +- ch.qos.logback:logback-classic:jar:1.5.38:compile
[INFO] | | | | \- ch.qos.logback:logback-core:jar:1.5.38:compile
[INFO] | | | +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.25.5:compile
[INFO] | | | | \- org.apache.logging.log4j:log4j-api:jar:2.25.5:compile
[INFO] | | | \- org.slf4j:jul-to-slf4j:jar:2.0.18:compile
[INFO] | | +- org.springframework.boot:spring-boot-autoconfigure:jar:4.1.1:compile
[INFO] | | +- jakarta.annotation:jakarta.annotation-api:jar:3.0.0:compile
[INFO] | | \- org.yaml:snakeyaml:jar:2.6:compile
[INFO] | +- org.springframework.boot:spring-boot-starter-jackson:jar:4.1.1:compile
[INFO] | | \- org.springframework.boot:spring-boot-jackson:jar:4.1.1:compile
[INFO] | | \- tools.jackson.core:jackson-databind:jar:3.1.5:compile
[INFO] | | +- com.fasterxml.jackson.core:jackson-annotations:jar:2.21:compile
[INFO] | | \- tools.jackson.core:jackson-core:jar:3.1.5:compile
[INFO] | +- org.springframework.boot:spring-boot-starter-tomcat:jar:4.1.1:compile
[INFO] | | +- org.springframework.boot:spring-boot-starter-tomcat-runtime:jar:4.1.1:compile
[INFO] | | | +- org.apache.tomcat.embed:tomcat-embed-core:jar:11.0.24:compile
[INFO] | | | +- org.apache.tomcat.embed:tomcat-embed-el:jar:11.0.24:compile
[INFO] | | | \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:11.0.24:compile
[INFO] | | \- org.springframework.boot:spring-boot-tomcat:jar:4.1.1:compile
[INFO] | +- org.springframework.boot:spring-boot-http-converter:jar:4.1.1:compile
[INFO] | | +- org.springframework.boot:spring-boot:jar:4.1.1:compile
[INFO] | | | \- org.springframework:spring-context:jar:7.0.9:compile
[INFO] | | \- org.springframework:spring-web:jar:7.0.9:compile
[INFO] | | +- org.springframework:spring-beans:jar:7.0.9:compile
[INFO] | | \- io.micrometer:micrometer-observation:jar:1.17.1:compile
[INFO] | | \- io.micrometer:micrometer-commons:jar:1.17.1:compile
[INFO] | \- org.springframework.boot:spring-boot-webmvc:jar:4.1.1:compile
[INFO] | +- org.springframework.boot:spring-boot-servlet:jar:4.1.1:compile
[INFO] | \- org.springframework:spring-webmvc:jar:7.0.9:compile
[INFO] | +- org.springframework:spring-aop:jar:7.0.9:compile
[INFO] | \- org.springframework:spring-expression:jar:7.0.9:compile
...

4版がどこに書いてあるかをたどる

自分の pom には版が書かれていません。親の 、さらにその親の ()までたどると、Tomcat の版が1か所に書かれています。この BOM が管理する数は数え方で変わり、版プロパティなら 195 個、 直下のエントリなら 652 個、取り込んだ他の BOM を展開した後なら 1911 個でした。

3つの pom からの抜粋(インデントは詰めてある)設定ファイル
<!-- (1) 自分の pom.xml(start.spring.io 生成)。依存に版が無い -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>4.1.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc</artifactId>
</dependency>
 
<!-- (2) spring-boot-starter-parent-4.1.1.pom。親がもう1段ある -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>4.1.1</version>
</parent>
 
<!-- (3) spring-boot-dependencies-4.1.1.pom(BOM)。版はここにある -->
<tomcat.version>11.0.24</tomcat.version>
...
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>${tomcat.version}</version>
</dependency>

5npm と並べる — 版の組み合わせを誰が決めるか

npm では、各が自分の依存の版の範囲を宣言し、それを解決した結果が lockfile に残ります。組み合わせはプロジェクトごとに解決されます。 では、組み合わせる版の一覧を Boot の各リリースが BOM として配り、利用側はそれを親としてします。Boot のリファレンスはこれを curated list(選んで整えた一覧)と呼んでいます。

依存の版の決まり方表
| npm | Maven + Spring Boot の BOM
---------------------+--------------------------------+------------------------------------------
依存を書く場所 | package.json | pom.xml
版の書き方 | 受け入れる範囲を書く | 書かない(BOM の表から引く。書けば上書きできる)
組み合わせを決める側 | 各パッケージの宣言を解決する | Boot のリリース(spring-boot-dependencies)
組み合わせの置き場 | lockfile(解決した結果) | BOM(Boot が先に決めた一覧。Boot の版ごと)
Boot を上げると | - | 管理下の依存の版もまとめて変わる

図やコードに出てくる用語(タップで説明)