Spring Boot の起動が遅い/落ちるを診断:Auto-config レポートと条件分岐の切り分け
Spring Boot アプリケーションの起動時に、予期せぬエラーで落ちたり、異常に時間がかかったりする経験はありませんか?
開発中は問題なく動いていたのに、本番環境や CI/CD パイプラインで突然起動しなくなるケースは珍しくありません。こうした問題の多くは、Spring Boot の自動構成(Auto-configuration)が期待通りに動作していないことが原因です。本記事では、Auto-configuration レポートを活用した診断方法と、条件分岐の仕組みを理解することで、起動トラブルを効率的に解決する手法を解説します。
背景
Spring Boot の自動構成の仕組み
Spring Boot は「設定より規約(Convention over Configuration)」の原則に基づき、開発者が明示的に設定を書かなくても、クラスパス上のライブラリや環境変数を検知して、必要な Bean を自動的に構成してくれます。
この便利な機能を実現しているのが Auto-configuration です。Spring Boot は起動時に、クラスパス上の JAR ファイルや設定情報をスキャンし、条件に応じて様々な Bean を自動生成します。
以下の図は、Spring Boot の起動プロセスと Auto-configuration の動作フローを示しています。
mermaidflowchart TD
start["アプリケーション起動"] --> scan["クラスパススキャン"]
scan --> check["条件評価<br/>@Conditional"]
check --> match{条件一致?}
match -->|Yes| enable["Auto-configuration<br/>有効化"]
match -->|No| skip["スキップ"]
enable --> bean["Bean 生成"]
skip --> next["次の設定へ"]
bean --> next
next --> complete{全設定完了?}
complete -->|No| check
complete -->|Yes| done["起動完了"]
図で理解できる要点:
- Spring Boot は起動時に自動的にクラスパスをスキャンします
- 各 Auto-configuration クラスには条件(@Conditional)が付与されています
- 条件が満たされた場合のみ、その設定が有効化されます
Auto-configuration が機能する条件
Spring Boot の Auto-configuration は、様々な条件アノテーションを使って「いつ有効化されるか」を制御しています。
主な条件アノテーションには以下のようなものがあります。
| # | アノテーション | 説明 |
|---|---|---|
| 1 | @ConditionalOnClass | 特定のクラスがクラスパスに存在する場合に有効化 |
| 2 | @ConditionalOnMissingClass | 特定のクラスが存在しない場合に有効化 |
| 3 | @ConditionalOnBean | 特定の Bean が定義されている場合に有効化 |
| 4 | @ConditionalOnMissingBean | 特定の Bean が定義されていない場合に有効化 |
| 5 | @ConditionalOnProperty | 特定のプロパティが設定されている場合に有効化 |
| 6 | @ConditionalOnResource | 特定のリソースファイルが存在する場合に有効化 |
これらの条件が複雑に組み合わさることで、柔軟な自動構成が実現されていますが、同時にトラブルの原因にもなります。
課題
起動トラブルの典型的なパターン
Spring Boot アプリケーションの起動時に発生するトラブルは、大きく分けて以下の 3 つのパターンに分類できます。
パターン 1:起動が遅い
アプリケーションは最終的に起動するものの、起動に数分以上かかってしまうケースです。
主な原因:
- 不要な Auto-configuration が大量に実行されている
- データベース接続のタイムアウト待ち
- 外部サービスへの接続試行が繰り返されている
- クラスパススキャンの範囲が広すぎる
パターン 2:起動時にエラーで落ちる
アプリケーションが起動途中で例外を投げて終了してしまうケースです。
典型的なエラーコード:
vbnetError: APPLICATION FAILED TO START
Description:
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
Reason: Failed to determine a suitable driver class
perlError: BeanCreationException
Description:
Error creating bean with name 'entityManagerFactory' defined in class path resource
Reason: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException
主な原因:
- 必要な依存ライブラリが不足している
- 環境変数や設定プロパティが不足している
- Bean の依存関係が循環している
- 競合する Bean 定義が存在する
パターン 3:特定環境でのみ起動しない
開発環境では正常に動作するのに、本番環境や Docker コンテナ内でのみ起動しないケースです。
主な原因:
- 環境変数の設定漏れ
- プロファイル(dev, prod)の切り替え不備
- クラスパス上のライブラリバージョンの違い
- ファイルシステムのパーミッション問題
以下の図は、これらのトラブルパターンと原因の関係性を示しています。
mermaidflowchart LR
trouble["起動トラブル"] --> slow["パターン1<br/>起動が遅い"]
trouble --> error["パターン2<br/>エラーで落ちる"]
trouble --> env["パターン3<br/>特定環境でのみ失敗"]
slow --> cause1["不要な<br/>Auto-config"]
slow --> cause2["接続タイムアウト"]
error --> cause3["依存不足"]
error --> cause4["Bean 競合"]
env --> cause5["環境変数不足"]
env --> cause6["プロファイル<br/>設定ミス"]
図で理解できる要点:
- 起動トラブルは 3 つの主要パターンに分類される
- それぞれのパターンに特有の原因がある
- 原因を特定することが解決への第一歩
なぜ診断が難しいのか
Spring Boot の起動トラブルの診断が難しい理由は、以下の点にあります。
透明性の低さ Auto-configuration は便利ですが、裏で何が起きているのかが見えにくいという特性があります。どの Bean が生成され、どの設定がスキップされたのかを把握するのは容易ではありません。
エラーメッセージの複雑さ スタックトレースが長く、本質的な原因が埋もれてしまうことがあります。また、エラーメッセージが抽象的で、具体的な解決策が分かりにくいケースも多いでしょう。
環境依存性 開発環境と本番環境でクラスパスや環境変数が異なるため、問題の再現が難しい場合があります。
解決策
Auto-configuration レポートの活用
Spring Boot は、起動時にどの Auto-configuration が有効化され、どれがスキップされたのかを詳細に記録する Auto-configuration レポート を生成できます。
このレポートを活用することで、起動プロセスの透明性が大幅に向上し、問題の切り分けが容易になります。
レポート出力の有効化方法
Auto-configuration レポートを出力するには、以下の 2 つの方法があります。
方法 1:コマンドライン引数で指定
起動時に --debug フラグを付けて実行します。
bashjava -jar myapp.jar --debug
方法 2:application.properties で設定
設定ファイルに以下を追加します。
properties# Auto-configuration レポートを有効化
debug=true
方法 3:環境変数で設定
環境変数を使って有効化することも可能です。
bashexport DEBUG=true
java -jar myapp.jar
レポートの読み方
Auto-configuration レポートは、起動ログの中に以下のような形式で出力されます。
sql============================
CONDITIONS EVALUATION REPORT
============================
Positive matches:
-----------------
DataSourceAutoConfiguration matched:
- @ConditionalOnClass found required classes 'javax.sql.DataSource', 'org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType' (OnClassCondition)
DataSourceAutoConfiguration.PooledDataSourceConfiguration matched:
- @ConditionalOnMissingBean found no beans of type 'javax.sql.DataSource' (OnBeanCondition)
- @ConditionalOnProperty (spring.datasource.type) matched (OnPropertyCondition)
Negative matches:
-----------------
RedisAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.data.redis.core.RedisOperations' (OnClassCondition)
MongoAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'com.mongodb.client.MongoClient' (OnClassCondition)
レポートは Positive matches(有効化された設定)と Negative matches(スキップされた設定)に分かれています。
Positive matches の読み方:
- どの Auto-configuration が有効化されたかが分かります
- 各設定の下に、条件が満たされた理由が記載されています
- 例:DataSourceAutoConfiguration は、必要なクラスがクラスパスに存在したため有効化
Negative matches の読み方:
- どの Auto-configuration がスキップされたかが分かります
- スキップされた理由が明記されています
- 例:RedisAutoConfiguration は、必要なクラスが見つからなかったためスキップ
条件分岐の切り分け手法
Auto-configuration レポートを確認したら、次は具体的な条件の切り分けを行います。
ステップ 1:期待する設定が有効化されているか確認
まず、自分が期待している Auto-configuration が Positive matches に含まれているかを確認します。
もし Negative matches に含まれている場合は、スキップされた理由を確認しましょう。
sqlNegative matches:
-----------------
DataSourceAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'com.zaxxer.hikari.HikariDataSource'
この例では、HikariCP のクラスが見つからないため、DataSource の自動構成がスキップされています。
ステップ 2:不足している依存関係を特定
Negative matches の理由が @ConditionalOnClass did not find required class の場合、必要なライブラリが不足しています。
解決方法:
依存関係を追加します(Maven の例)。
xml<!-- HikariCP を追加 -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</dependency>
Yarn や npm ではなく、Spring Boot では Maven や Gradle を使うことが一般的ですが、プロジェクトルールに従い Yarn ベースの設定例も示します。
ただし、Spring Boot プロジェクトでは通常 pom.xml(Maven)または build.gradle(Gradle)を使用します。
ステップ 3:プロパティ設定の確認
@ConditionalOnProperty による条件が満たされていない場合、必要なプロパティを設定します。
sqlNegative matches:
-----------------
RabbitAutoConfiguration:
Did not match:
- @ConditionalOnProperty (spring.rabbitmq.host) did not find property 'spring.rabbitmq.host'
この場合、application.properties または application.yml に設定を追加します。
properties# RabbitMQ の接続設定を追加
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
ステップ 4:競合する Bean の特定
Positive matches に同じ種類の Bean が複数含まれている場合、競合が発生している可能性があります。
rubyError: BeanDefinitionOverrideException
Description:
The bean 'dataSource', defined in class path resource [com/example/config/DatabaseConfig.class], could not be registered. A bean with that name has already been defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class] and overriding is disabled.
解決方法 1:Bean の上書きを許可
properties# Bean の上書きを許可(非推奨)
spring.main.allow-bean-definition-overriding=true
解決方法 2:不要な Auto-configuration を除外
カスタム設定を使う場合は、自動構成を除外します。
java@SpringBootApplication(exclude = {
DataSourceAutoConfiguration.class
})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
デバッグログの強化
Auto-configuration レポートに加えて、Spring のログレベルを調整することで、より詳細な情報を得られます。
properties# Spring Framework のコアロギングを DEBUG レベルに
logging.level.org.springframework=DEBUG
# Auto-configuration の詳細ログ
logging.level.org.springframework.boot.autoconfigure=DEBUG
# Bean の生成プロセスを詳細表示
logging.level.org.springframework.beans.factory=DEBUG
これらの設定により、Bean の生成順序や依存関係の解決プロセスが詳細に記録されます。
ただし、ログ量が膨大になるため、トラブルシューティング時のみ有効化し、本番環境では無効化することを推奨します。
具体例
例 1:DataSource が自動構成されない問題
発生したエラー
アプリケーション起動時に以下のエラーが発生しました。
vbnetError: APPLICATION FAILED TO START
***************************
APPLICATION FAILED TO START
***************************
Description:
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
Reason: Failed to determine a suitable driver class
Action:
Consider the following:
If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).
診断手順
手順 1:Auto-configuration レポートを有効化
bashjava -jar myapp.jar --debug > startup.log 2>&1
手順 2:レポートの確認
startup.log を開き、DataSource 関連の設定を検索します。
sqlNegative matches:
-----------------
DataSourceAutoConfiguration:
Did not match:
- @ConditionalOnClass found required class 'javax.sql.DataSource'
- @ConditionalOnProperty (spring.datasource.url) did not find property 'spring.datasource.url' (OnPropertyCondition)
診断結果:
- 必要なクラスは存在している
- しかし
spring.datasource.urlプロパティが設定されていない
解決方法
application.properties にデータベース接続情報を追加します。
properties# データベース接続設定
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=secret
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
さらに、MySQL ドライバの依存関係が含まれているか確認します(Maven の例)。
xml<!-- MySQL Connector を追加 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
検証
設定を追加した後、再度起動します。
bashjava -jar myapp.jar --debug
Auto-configuration レポートで DataSourceAutoConfiguration が Positive matches に含まれていることを確認します。
sqlPositive matches:
-----------------
DataSourceAutoConfiguration matched:
- @ConditionalOnClass found required classes 'javax.sql.DataSource' (OnClassCondition)
- @ConditionalOnProperty (spring.datasource.url) matched (OnPropertyCondition)
DataSourceAutoConfiguration.PooledDataSourceConfiguration matched:
- @ConditionalOnMissingBean found no beans of type 'javax.sql.DataSource' (OnBeanCondition)
例 2:Redis の自動構成が意図せず有効化される問題
発生した問題
アプリケーションの起動が非常に遅く、ログを確認すると Redis への接続試行が繰り返されていました。
ini2025-01-15 10:23:45.123 WARN 12345 --- [main] io.lettuce.core.cluster.ClusterTopologyRefresh : Unable to connect to [localhost:6379]: Connection refused
2025-01-15 10:23:50.456 WARN 12345 --- [main] io.lettuce.core.cluster.ClusterTopologyRefresh : Unable to connect to [localhost:6379]: Connection refused
しかし、このアプリケーションでは Redis を使用する予定はありませんでした。
診断手順
手順 1:Auto-configuration レポートを確認
bashjava -jar myapp.jar --debug 2>&1 | grep -A 10 "RedisAutoConfiguration"
レポートを確認すると、RedisAutoConfiguration が有効化されていました。
markdownPositive matches:
-----------------
RedisAutoConfiguration matched:
- @ConditionalOnClass found required classes 'org.springframework.data.redis.core.RedisOperations' (OnClassCondition)
手順 2:依存関係の確認
pom.xml を確認したところ、別のライブラリが Redis を推移的依存関係として含んでいました。
xml<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
解決方法
Redis を使用しない場合は、以下のいずれかの方法で対処します。
方法 1:Auto-configuration を除外
java@SpringBootApplication(exclude = {
RedisAutoConfiguration.class,
RedisRepositoriesAutoConfiguration.class
})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
方法 2:不要な依存関係を除外
Redis が不要な場合は、依存関係自体を削除します。
xml<!-- 不要な依存関係を削除 -->
<!--
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
-->
方法 3:プロパティで無効化
properties# Redis の自動構成を無効化
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration
検証
再度起動し、Auto-configuration レポートで RedisAutoConfiguration が Negative matches に含まれていることを確認します。
sqlNegative matches:
-----------------
RedisAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.data.redis.core.RedisOperations' (OnClassCondition)
起動時間も大幅に短縮され、Redis への接続試行も行われなくなりました。
例 3:Bean の循環依存エラー
発生したエラー
アプリケーション起動時に以下のエラーが発生しました。
markdownError: BeanCurrentlyInCreationException
***************************
APPLICATION FAILED TO START
***************************
Description:
The dependencies of some of the beans in the application context form a cycle:
┌─────┐
| serviceA defined in file [ServiceA.class]
↑ ↓
| serviceB defined in file [ServiceB.class]
↑ ↓
| serviceC defined in file [ServiceC.class]
└─────┘
Action:
Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans.
以下の図は、Bean の循環依存の状態を示しています。
mermaidflowchart LR
A["ServiceA"] --> B["ServiceB"]
B --> C["ServiceC"]
C --> A
style A fill:#ffcccc
style B fill:#ffcccc
style C fill:#ffcccc
図で理解できる要点:
- ServiceA、ServiceB、ServiceC が相互に依存している
- この循環依存により Bean の生成ができない
- 依存関係を見直す必要がある
診断手順
手順 1:依存関係の確認
各サービスクラスのコンストラクタを確認します。
java// ServiceA.java
@Service
public class ServiceA {
private final ServiceB serviceB;
// ServiceB に依存
public ServiceA(ServiceB serviceB) {
this.serviceB = serviceB;
}
}
java// ServiceB.java
@Service
public class ServiceB {
private final ServiceC serviceC;
// ServiceC に依存
public ServiceB(ServiceC serviceC) {
this.serviceC = serviceC;
}
}
java// ServiceC.java
@Service
public class ServiceC {
private final ServiceA serviceA;
// ServiceA に依存(循環!)
public ServiceC(ServiceA serviceA) {
this.serviceA = serviceA;
}
}
解決方法
循環依存を解消するには、以下の方法があります。
方法 1:@Lazy アノテーションを使用
循環の一部を遅延初期化にします。
java// ServiceC.java を修正
@Service
public class ServiceC {
private final ServiceA serviceA;
// @Lazy で遅延初期化
public ServiceC(@Lazy ServiceA serviceA) {
this.serviceA = serviceA;
}
}
方法 2:Setter インジェクションを使用
コンストラクタインジェクションから Setter インジェクションに変更します。
java// ServiceC.java を修正
@Service
public class ServiceC {
private ServiceA serviceA;
// Setter インジェクション
@Autowired
public void setServiceA(ServiceA serviceA) {
this.serviceA = serviceA;
}
}
方法 3:設計を見直す(推奨)
根本的な解決として、依存関係の設計を見直します。
java// 共通インターフェースを抽出
public interface SharedService {
void execute();
}
// ServiceA を修正
@Service
public class ServiceA implements SharedService {
// ServiceB への依存を削除
@Override
public void execute() {
// 実装
}
}
この例では、循環依存を避けるために、共通のインターフェースを抽出したり、依存関係を一方向にするなどの設計変更を行います。
例 4:プロファイル別の起動トラブル
発生した問題
開発環境(dev プロファイル)では正常に起動するが、本番環境(prod プロファイル)では起動しない問題が発生しました。
診断手順
手順 1:プロファイル別の設定を確認
bash# dev プロファイルで起動(成功)
java -jar myapp.jar --spring.profiles.active=dev --debug
# prod プロファイルで起動(失敗)
java -jar myapp.jar --spring.profiles.active=prod --debug
手順 2:Auto-configuration レポートの比較
dev と prod のレポートを比較します。
bash# dev のレポートを保存
java -jar myapp.jar --spring.profiles.active=dev --debug > dev-report.log 2>&1
# prod のレポートを保存
java -jar myapp.jar --spring.profiles.active=prod --debug > prod-report.log 2>&1
# 差分を確認
diff dev-report.log prod-report.log
手順 3:設定ファイルの確認
application-prod.properties を確認すると、必要な設定が不足していました。
properties# application-prod.properties(不完全)
spring.datasource.url=jdbc:mysql://prod-db-server:3306/mydb
# username と password が不足!
解決方法
不足している設定を追加します。
properties# application-prod.properties(完全版)
spring.datasource.url=jdbc:mysql://prod-db-server:3306/mydb
spring.datasource.username=${DB_USERNAME}
spring.datasource.password=${DB_PASSWORD}
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 接続プール設定
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.minimum-idle=5
環境変数で機密情報を管理します。
bash# 環境変数を設定
export DB_USERNAME=prod_user
export DB_PASSWORD=secure_password
# アプリケーションを起動
java -jar myapp.jar --spring.profiles.active=prod
まとめ
Spring Boot アプリケーションの起動トラブルは、Auto-configuration の仕組みを理解し、適切な診断ツールを活用することで効率的に解決できます。
本記事で紹介した手法をまとめます。
診断の基本ステップ:
| # | ステップ | 実施内容 |
|---|---|---|
| 1 | Auto-configuration レポートを有効化 | --debug フラグまたは debug=true を設定 |
| 2 | Positive / Negative matches を確認 | どの設定が有効化/スキップされたかを把握 |
| 3 | 条件不一致の原因を特定 | クラス不足、プロパティ不足、Bean 競合などを確認 |
| 4 | 必要な修正を実施 | 依存関係追加、設定追加、除外設定など |
| 5 | 再度レポートで検証 | 期待する設定が有効化されたことを確認 |
重要なポイント:
Auto-configuration レポートは、起動プロセスを可視化する最も強力なツールです。トラブル発生時は必ず最初に確認しましょう。
条件アノテーション(@ConditionalOnClass、@ConditionalOnProperty など)の仕組みを理解することで、なぜ特定の設定が有効化されないのかを論理的に推測できます。
開発環境と本番環境の差異(クラスパス、環境変数、プロファイル)に注意を払い、プロファイル別の設定を適切に管理することが重要です。
不要な Auto-configuration は明示的に除外することで、起動時間の短縮とトラブルの予防につながりますね。
これらの手法を活用することで、Spring Boot アプリケーションの起動トラブルを迅速に解決し、開発効率を大幅に向上させることができるでしょう。
関連リンク
articleSpring Boot の起動が遅い/落ちるを診断:Auto-config レポートと条件分岐の切り分け
articleSpring Boot とは?2025 年版の強み・弱み・採用判断を 30 分で俯瞰
articleLodash vs ネイティブ(`Array.prototype`/`Object.*`):実行速度と可読性の実測
articlePostgreSQL vs MySQL 徹底比較:トランザクション・索引・JSON 機能の実測
articleSpring Boot の起動が遅い/落ちるを診断:Auto-config レポートと条件分岐の切り分け
articleLlamaIndex × OpenAI/Claude/Gemini 設定手順:モデル切替とコスト最適化
articleNode.js 25.x, 24.x, 22.x, 20.x の脆弱性対応:2025 年 12 月版で修正された 3 件の High Severity 問題の詳細
articleEmotion × Vite の最短構築:開発高速化とソースマップ最適設定
blogiPhone 17シリーズの発表!全モデルiPhone 16から進化したポイントを見やすく整理
blogGoogleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
blog【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
blogGoogleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
blogPixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
blogフロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
review今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
reviewついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
review愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
review週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
review新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
review科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来