最初のSpring Bootアプリケーション
たった1つの@SpringBootApplicationアノテーションでアプリケーション全体を起動できる—Spring Bootの魔法は3つのアノテーションの巧みな組み合わせにあります。
1. 学ぶ内容
@SpringBootApplicationアノテーションの分解と組み合わせの原理- メイン起動クラス
main()メソッドとSpringApplication.run()の実行フロー application.propertiesとapplication.yml設定ファイル形式- Spring Bootバナーのカスタマイズと起動ログの読み方
- 最初の"Hello OrderFlow"エンドポイントの実行
2. 新規プロジェクトに関する実話
(1) ペインポイント:プロジェクトセットアップに半日かかる
Aliceは入社当時, 従来のSpring MVCを使っていた時の経験を思い出しました。プロジェクトを作成するにはweb.xml, applicationContext.xml, spring-mvc.xmlの設定が必要で, TomcatのインストールとJNDIデータソースの設定も必要でした。プロジェクトを起動するだけで半日かかり, 起動順序やBean読み込みの問題のデバッグはおろかありません。
(2) Spring Bootによる解決策
Spring Bootではアノテーション1つとメインメソッド1つだけです。
@SpringBootApplication
public class OrderFlowApplication {
public static void main(String[] args) {
SpringApplication.run(OrderFlowApplication.class, args);
}
}
(3) 成果
AliceはSpring Bootを使ってOrderFlowプロジェクトを作成しました。ゼロから最初のAPIレスポンスまで5分しかかかりませんでした。XML不要, 外部コンテナ不要, 起動ログも明確で読みやすい。
3. @SpringBootApplicationアノテーションの分解
(1) 3つのアノテーションの組み合わせ
@SpringBootApplicationは複合アノテーションであり、以下の3つのアノテーションを同時に使用するのと同等です。
graph TB
A["@SpringBootApplication"] --> B["@SpringBootConfiguration"]
A --> C["@EnableAutoConfiguration"]
A --> D["@ComponentScan"]
B --> B1["クラスを設定Beanの<br/>ソースとしてマーク"]
C --> C1["クラスパスに基づく<br/>自動設定を起動"]
D --> D1["同じパッケージツリー内の<br/>コンポーネントをスキャン"]
| アノテーション | 機能 | 従来の記述での同等表現 |
|---|---|---|
@SpringBootConfiguration |
現在のクラスを設定クラスとしてマーク | @Configuration |
@EnableAutoConfiguration |
自動設定の有効化 | @EnableAutoConfiguration |
@ComponentScan |
コンポーネントスキャン | <context:component-scan> |
(2) @ComponentScanのスキャンルール
@ComponentScanはデフォルトでメイン起動クラスを含むパッケージとそのすべてのサブパッケージをスキャンします。
com.orderflow ← メイン起動クラスを含むパッケージ
├── OrderFlowApplication.java ← @SpringBootApplication
├── controller/ ← @ComponentScanでスキャン対象
│ └── OrderController.java
├── service/ ← @ComponentScanでスキャン対象
│ └── OrderService.java
└── repository/ ← @ComponentScanでスキャン対象
└── OrderRepository.java
com.other ← ⚠️ スキャン対象外!
4. SpringApplication.run()の起動プロセス
(1) 起動シーケンス
SpringApplication.run()の実行プロセスは慎重に設計されたパイプラインです。
sequenceDiagram
participant Main as main()
participant SA as SpringApplication
participant Ctx as ApplicationContext
participant Bean as Beans
Main->>SA: new SpringApplication()
SA->>SA: プライマリソースの推論
SA->>SA: Webアプリケーションタイプの確認
SA->>SA: イニシャライザとリスナーの読み込み
Main->>SA: run(args)
SA->>SA: ブートストラップコンテキストの作成
SA->>SA: 環境の準備
SA->>SA: バナーの表示
SA->>Ctx: ApplicationContextの作成
SA->>Ctx: コンテキストの準備 (ソースの登録)
SA->>Ctx: コンテキストのリフレッシュ
Ctx->>Bean: Beanのインスタンス化
Ctx->>Bean: 自動設定
SA->>SA: Runnerの呼び出し
SA->>Main: ApplicationContextを返却
(2) Webアプリケーションタイプの判定
Spring Bootはアプリケーションタイプを自動検出します。
| 条件 | タイプ | 使用コンテナ |
|---|---|---|
クラスパスにspring-webmvcが含まれる |
SERVLET | Tomcat / Jetty / Undertow |
クラスパスにspring-webfluxはあるがspring-webmvcはない |
REACTIVE | Netty |
| なし | NONE | 組み込みコンテナなし |
(1) ▶ サンプル:SpringApplication起動のカスタマイズ
@SpringBootApplication
public class OrderFlowApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(OrderFlowApplication.class);
app.setBannerMode(Banner.Mode.CONSOLE);
app.setWebApplicationType(WebApplicationType.SERVLET);
app.run(args);
}
}
出力:
// 実行成功
5. 設定ファイル形式
(1) Properties vs. YAML
Spring Bootは2つの設定ファイル形式をサポートしており, 機能的には同等ですが構文が異なります。
(1) ▶ サンプル:application.propertiesの書き方
server.port=8080
spring.application.name=orderflow-service
spring.datasource.url=jdbc:mysql://localhost:3306/orderflow
spring.datasource.username=root
spring.datasource.password=secret
spring.jpa.hibernate.ddl-auto=update
出力:
// 実行成功
(2) ▶ サンプル:application.ymlの書き方
server:
port: 8080
spring:
application:
name: orderflow-service
datasource:
url: jdbc:mysql://localhost:3306/orderflow
username: root
password: secret
jpa:
hibernate:
ddl-auto: update
出力:
設定が反映されました。
| 項目 | Properties | YAML |
|---|---|---|
| 階層構造 | .で区切る |
インデントで階層を表現 |
| 可読性 | シンプルなキー・バリュー, フラット | 階層が明確, ネストに適している |
| リストサポート | list[0]=a |
- aより直感的 |
| 重複プレフィックス | 毎回記述必要 | 同レベルでプレフィックスを共有 |
| パース性能 | より速い | やや遅い (階層の解析が必要) |
| 優先度 | 同じ | 同じ (両方存在する場合propertiesが優先) |
(2) よく使う設定オプションのクイックリファレンス
| 設定オプション | デフォルト値 | 説明 |
|---|---|---|
server.port |
8080 | アプリケーションのリスニングポート |
spring.application.name |
— | アプリケーション名 |
server.servlet.context-path |
/ | コンテキストパス |
spring.main.banner-mode |
console | バナー表示モード |
spring.jpa.show-sql |
false | SQLの出力 |
logging.level.root |
INFO | グローバルログレベル |
6. バナーと起動ログのカスタマイズ
(1) カスタムバナー
src/main/resources/banner.txtにカスタムバナーを配置すると、Spring Boot起動時に自動的に表示されます。
(1) ▶ サンプル:OrderFlowカスタムバナー
____ _ ____ __
/ ___| _ __ __ _| |_ ___ / ___|| | ___ _ __
| | | '_ \ / _` | __/ _ \ \___ \| |/ _ \| '_ \
| |___ | | | | (_| | || __/ ___) | | (_) | | | |
\____||_| |_|\__,_|\__\___| |____/|_|\___/|_| |_|
:: OrderFlow Service :: v${application.version:1.0.0}
:: Spring Boot ${spring-boot.version} ::
出力:
実行成功
(2) 起動ログの読み方
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | | || (_| | / / / /
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.2.5)
2024-01-15 10:00:01.123 INFO 12345 --- [main] c.o.OrderFlowApplication : Starting OrderFlowApplication
2024-01-15 10:00:03.456 INFO 12345 --- [main] o.s.b.w.e.t.TomcatWebServer : Tomcat initialized with port 8080 (http)
2024-01-15 10:00:04.789 INFO 12345 --- [main] o.s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories
2024-01-15 10:00:06.012 INFO 12345 --- [main] c.o.OrderFlowApplication : Started in 5.123 seconds
| ログキーワード | 意味 |
|---|---|
Starting OrderFlowApplication |
アプリケーション起動中 |
Tomcat initialized with port |
組み込みTomcat起動 |
Bootstrapping Spring Data JPA |
JPAリポジトリの自動設定 |
Started in X seconds |
起動完了, 所要時間 |
7. 最初の"Hello OrderFlow"エンドポイントの実行
(1) ▶ サンプル:Hello OrderFlowコントローラ
package com.orderflow.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@RestController
public class HelloController {
@GetMapping("/api/hello")
public Map<String, String> hello() {
return Map.of(
"message", "Hello, OrderFlow!",
"timestamp", java.time.Instant.now().toString()
);
}
}
出力:
HTTP 200 OK
Content-Type: application/json
{"status":"success","data":{}}
$ curl http://localhost:8080/api/hello
{"message":"Hello, OrderFlow!","timestamp":"2024-01-15T10:00:00Z"}
(2) ▶ サンプル:@Valueを使った設定インジェクション
@RestController
public class HelloController {
@Value("${spring.application.name}")
private String appName;
@GetMapping("/api/info")
public Map<String, String> info() {
return Map.of(
"application", appName,
"javaVersion", System.getProperty("java.version")
);
}
}
出力:
// 実行成功
8. 総合サンプル:OrderFlowの完全な起動設定
// src/main/java/com/orderflow/OrderFlowApplication.java
package com.orderflow;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class OrderFlowApplication {
public static void main(String[] args) {
SpringApplication.run(OrderFlowApplication.class, args);
}
}
// src/main/java/com/orderflow/controller/OrderFlowController.java
package com.orderflow.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.Instant;
import java.util.Map;
@RestController
public class OrderFlowController {
@Value("${spring.application.name:orderflow}")
private String appName;
@GetMapping("/api/health")
public Map<String, Object> health() {
return Map.of(
"status", "UP",
"application", appName,
"timestamp", Instant.now()
);
}
}
# src/main/resources/application.yml
server:
port: 8080
spring:
application:
name: orderflow-service
$ curl http://localhost:8080/api/health
{"status":"UP","application":"orderflow-service","timestamp":"2024-01-15T10:00:00Z"}
❓ よくある質問
propertiesとYAMLは共存できますか?propertiesの定義が優先されます。混乱を避けるためどちらか1つを使用することを推奨します。YAMLの方が階層が明確なため推奨します。spring.main.banner-mode=offを設定するか, コードでapp.setBannerMode(Banner.Mode.OFF)を指定してください。server.port=8081に変更するか, ポートを使用しているプロセスを特定して終了してください。lsof -i :8080 (Linux/Mac)またはnetstat -ano | findstr 8080 (Windows)を使用します。ddl-auto=validateがリモートデータベースへの接続で遅延する;3)不要な自動設定が除外されていない。--debugモードで詳細を確認してください。<mainClass>で設定するか, IDEでmainメソッドを含むクラスを直接実行してください。Spring Boot Maven Pluginはパッケージ時に自動検出します。📖 まとめ
@SpringBootApplication=@Configuration+@EnableAutoConfiguration+@ComponentScan- メイン起動クラスはルートパッケージに配置し, コンポーネントスキャンがすべてのサブパッケージをカバーするようにする
SpringApplication.run()は環境構築 → コンテキスト作成 → リフレッシュ → Beanインスタンス化の完全なプロセスを実行- YAMLとPropertiesは機能的に同等。YAMLは階層が明確, Propertiesはパースが速い
banner.txtでバナーをカスタマイズ。起動ログで起動問題の診断が可能
📝 練習問題
-
基本問題 (難易度 ⭐):Spring Bootプロジェクトを作成し,
banner.txtをカスタマイズし, サービスポートを9090に変更し, 起動後に/api/helloエンドポイントにアクセスできることを確認してください。 -
応用問題 (難易度 ⭐⭐):
SpringApplication.run()をSpringApplicationBuilderに置き換え, バナーを無効にし, ログレベルをDEBUGに設定し, アプリケーション名とJavaバージョンを返す/api/app-infoエンドポイントをカスタマイズしてください。 -
チャレンジ問題 (難易度 ⭐⭐⭐):
StartupListenerとApplicationListener<ApplicationStartedEvent>を実装し, アプリケーションの起動時間を記録してログに出力してください。Spring Bootのイベントメカニズムの設計意図について考察してください。



