サンプルコードで身につける: 3つの比較と Spring Boot との関係
解説で学んだ概念を、5つの具体例で確認します。素朴な例から実務寄りの例へと進みます。
1Ant で Boot の実行可能 JAR を作る: リファレンスの例そのままの build.xml と ivy.xml
4.1.1 のリファレンス(Build Systems)に載っている + の例を、依存だけ にして写したものです。Ivy が依存を compile と lib/runtime に取ってきて(強調した )、 の が を作ります(強調した build)。依存は に1本だけ書き(強調した dependency)、は Ivy がたどります。この例には resources をコピーする手順が無いので、 は に入りません。
<projectxmlns:ivy="antlib:org.apache.ivy.ant"xmlns:spring-boot="antlib:org.springframework.boot.ant"name="myapp" default="build"><property name="spring-boot.version" value="4.1.1" /><target name="resolve" description="--> retrieve dependencies with ivy"><ivy:retrieve pattern="lib/[conf]/[artifact]-[type]-[revision].[ext]" /></target><target name="classpaths" depends="resolve"><path id="compile.classpath"><fileset dir="lib/compile" includes="*.jar" /></path></target><target name="init" depends="classpaths"><mkdir dir="build/classes" /></target><target name="compile" depends="init" description="compile"><javac srcdir="src/main/java" destdir="build/classes" classpathref="compile.classpath" /></target><target name="build" depends="compile"><spring-boot:exejar destfile="build/myapp.jar" classes="build/classes"><spring-boot:lib><fileset dir="lib/runtime" /></spring-boot:lib></spring-boot:exejar></target></project># ivy.xml<ivy-module version="2.0"><info organisation="com.example" module="demo" /><configurations><conf name="compile" description="everything needed to compile this module" /><conf name="runtime" extends="compile" description="everything needed to run this module" /></configurations><dependencies><dependency org="org.springframework.boot" name="spring-boot-starter-webmvc"rev="${spring-boot.version}" conf="compile" /></dependencies></ivy-module>
2ant を実行して、出来た JAR を起動する
の起動には で Ivy の JAR のディレクトリと、spring-boot-antlib とその実行時依存5本(spring-boot-loader-tools、spring-core など)のディレクトリを渡しました。antlib の JAR 1本だけでは になります(末尾)。 の build まで resolve → classpaths → init → compile → build の順に進み、exejar がローダを埋め込んで JAR を作ります。 で起動すると /hello は 200 を返しましたが、application.properties が無いのでログに [demo] が出ません。ログ中の ms と seconds は共有環境での1回の値です。
resolve:[ivy:retrieve] :: resolving dependencies :: com.example#demo;working@...[ivy:retrieve] confs: [compile, runtime][ivy:retrieve] found org.springframework.boot#spring-boot-starter-webmvc;4.1.1 in public...(found 41行)[ivy:retrieve] 76 artifacts copied, 0 already retrieved (38403kB/66ms)classpaths:init:[mkdir] Created dir: /bt/l9-compare/ant-boot/build/classescompile:[javac] /bt/l9-compare/ant-boot/build.xml:23: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds[javac] Compiling 2 source files to /bt/l9-compare/ant-boot/build/classesbuild:[echo] Using start class com.example.demo.DemoApplication[echo] Using destination directory /bt/l9-compare/ant-boot/build[mkdir] Created dir: /bt/l9-compare/ant-boot/build/dependency[echo] Extracting spring-boot-loader to /bt/l9-compare/ant-boot/build/dependency[copy] Copying 1 resource to /bt/l9-compare/ant-boot/build/dependency[echo] Embedding spring-boot-loader v4.1.1...[jar] Building jar: /bt/l9-compare/ant-boot/build/myapp.jarBUILD SUCCESSFUL$ java -jar build/myapp.jar:: Spring Boot :: (v4.1.1)2026-10-03T00:25:53.670Z INFO 1 --- [ main] com.example.demo.DemoApplication : Starting DemoApplication using Java 25.0.4.1 with PID 1 (/bt/l9-compare/ant-boot/build/myapp.jar started by root in /)2026-10-03T00:25:54.144Z INFO 1 --- [ main] o.s.boot.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path '/'2026-10-03T00:25:54.150Z INFO 1 --- [ main] com.example.demo.DemoApplication : Started DemoApplication in 0.658 seconds (process running for 0.88)$ curl -i http://127.0.0.1:18411/helloHTTP/1.1 200Content-Type: application/jsonContent-Length: 19{"message":"hello"}# antlib の JAR 1本だけを -lib に置いたときの1回目(抜粋)# java.lang.NoClassDefFoundError: org/springframework/util/StringUtils
3同じソースから出来た3つの JAR の対比
同じ DemoApplication + HelloController + application.properties を、 の 、 の 、Ant の exejar でビルドした結果です。Maven と Gradle の は34本で名前も版も一致し、Ant は38本です。も Ant 版だけ項目が少なく、Spring-Boot-Version、、 がありません。この回に java -jar で起動したのは Ant 版だけで、Maven 版は後のレッスンで起動し、Gradle 版は起動していません。
出来た JARMaven : target/demo-0.0.1-SNAPSHOT.jar(包む前の JAR は .jar.original 3,244 B に改名)Gradle : build/libs/demo-0.0.1-SNAPSHOT.jar(別に jar タスクが -plain.jar 2,065 B を作る)Ant : build/myapp.jar(他の JAR は作らない)サイズ / エントリ数 / ローダのクラスMaven : 19,905,045 B / 170 / 99Gradle : 19,903,503 B / 167 / 99Ant : 20,109,103 B / 168 / 99BOOT-INF/libMaven : 34本Gradle : 34本(Maven と名前・版が一致)Ant : 38本BOOT-INF/classesMaven : クラス2個 + application.propertiesGradle : 同上(+ 空の static/ templates/)Ant : クラス2個だけマニフェストMaven : Main-Class / Start-Class / Spring-Boot-VersionSpring-Boot-Classpath-Index / Layers-IndexCreated-By: Maven JAR Plugin 3.5.1Gradle : 同上(Created-By は無し)Ant : Main-Class / Start-ClassSpring-Boot-Classes / Spring-Boot-Lib だけAnt-Version: Apache Ant 1.10.18そのほかの入りものMaven : META-INF/maven/.../pom.xml, pom.propertiesGradle : -Ant : META-INF/LICENSE.txt, NOTICE.txtjava -jar での起動Maven : この回は未起動(後のレッスンで起動と計測)Gradle : この回は未起動(エントリ一覧は Maven と一致)Ant : 起動して /hello → 200
4BOOT-INF/lib の差分: この ivy.xml では BOM が効かない
Maven(左)と Ant(右)の BOOT-INF/lib を並べた差分です。Gradle は Maven と同一でした。Ant 版にはの無い starter の JAR 5本が入り、Maven/Gradle のが足す がありません。版も JAR 3本( と micrometer の2系統)で違います。Maven/Gradle は Boot の が commons-logging を 1.3.6 に、micrometer を 1.17.1 に上書きしますが、リファレンスの例を写した ivy.xml では各 が直接書いた 1.3.5 と 1.16.7 のままでした。Ivy 側で BOM に当たるものを書く方法は試していません。
1c1< commons-logging-1.3.6.jar---> commons-logging-1.3.5.jar12,13c12,13< micrometer-commons-1.17.1.jar< micrometer-observation-1.17.1.jar---> micrometer-commons-1.16.7.jar> micrometer-observation-1.16.7.jar22d21< spring-boot-jarmode-tools-4.1.1.jar23a23,27> spring-boot-starter-4.1.1.jar> spring-boot-starter-jackson-4.1.1.jar> spring-boot-starter-logging-4.1.1.jar> spring-boot-starter-tomcat-4.1.1.jar> spring-boot-starter-tomcat-runtime-4.1.1.jar$ jar tf spring-boot-starter-4.1.1.jar # 4,767 B。クラス無しMETA-INF/MANIFEST.MFMETA-INF/LICENSE.txtMETA-INF/NOTICE.txt$ (そのマニフェストから)Implementation-Title: Core starter, including auto-configuration support, logging and YAMLSpring-Boot-Jar-Type: dependencies-starter# Gradle の dependencies 出力では、同じ上書きが -> で見える# commons-logging:commons-logging:1.3.5 -> 1.3.6# io.micrometer:micrometer-observation:1.16.7 -> 1.17.1
57つの観点で3つを並べる
このセクションで各ツールを見てきた7つの観点を、観点ごとに Ant・Maven・Gradle の順で並べました。違いは「置き場所・手順・依存を誰が決めるか」と「2回目に何を飛ばすか」に集まります。1.0 の年(Ant は単独の最初の正式版 1.1)と が生成するものも添えました。Gradle 1.0 のリリースノートは、依存の解決を Ivy から自前の仕組みに移したと書いていて、Ant+Ivy と Gradle は依存の取り方の系譜でつながっています。
1. 設定ファイルと書き方Ant : build.xml(XML)Maven : pom.xml(XML)Gradle : build.gradle(Groovy)か build.gradle.kts(Kotlin)+ settings.gradle(.kts)2. 置き場所は誰が決めるかAnt : 自分(全部 <property> に書く)Maven : Maven の規約(src/main/java など)Gradle : Maven の規約を借りる3. 手順の決め方Ant : <target> と depends を自分で書くMaven : ライフサイクルのフェーズにゴールが束縛される(順番は固定)Gradle : プラグインがタスクと依存関係(DAG)を登録する4. 依存の手に入れ方Ant : 人が lib/ に置く。Ivy を足せば取ってくる(この回の ivy.xml では BOM は効かなかった)Maven : 座標 → Maven Central → ~/.m2/repositoryGradle : 座標 → Maven Central → ~/.gradle/caches5. 2回目に飛ばすものAnt : javac・copy・jar は更新時刻で判定。テストは毎回Maven : compiler は Nothing to compile。テストは毎回。spring-boot:repackage が毎回 JAR を書き直す(jar:jar は Building jar を出さない)Gradle : タスクごとに入出力のハッシュ(UP-TO-DATE)。テストも飛ばす6. 出来上がるものAnt : build.xml 次第(今回は build/myapp.jar)Maven : target/<artifactId>-<version>.jar+ 包む前の .jar.originalGradle : build/libs/<name>-<version>.jar+ jar タスクが別に作る -plain.jar7. Spring Boot の乗り方Ant : spring-boot-antlib(exejar)+ Ivy。Boot のリファレンスの言葉ではnot particularly well supportedMaven : spring-boot-maven-plugin(repackage など11ゴール)Gradle : org.springframework.boot プラグイン(bootJar など)常駐プロセスAnt : 無いMaven : 無い(既定)Gradle : デーモン(既定オン)1.0 の年(Ant は 1.1)Ant : 1.1 2000-07-19(単独の最初の正式版)Maven : 1.0 2004-07-13(1.0-beta-2 は 2002-03-30)Gradle : 1.0 2012-06-12(0.7 は 2009-07-20)start.spring.io が生成するものAnt : 生成しないMaven : maven-projectGradle : gradle-project(Groovy。既定)gradle-project-kotlin