Spring Boot自動設定の仕組み
自動設定はSpring Bootの心臓部です。クラスパス内のクラスに基づいてBeanを自動登録し, 「設定より規約」の原則に従えるようにします。
1. 学ぶ内容
@EnableAutoConfigurationと自動設定読み込みメカニズム- 条件アノテーション:
@ConditionalOnClass/@ConditionalOnMissingBean/@ConditionalOnProperty - カスタムStarterの作成手順と命名規則
--debugモードで自動設定レポートを確認@SpringBootApplication(exclude = {...})で特定の自動設定を除外
2. フレームワーク開発者の実話
(1) ペインポイント:コンポーネント統合のたびに大量の設定を書く必要がある
AliceのチームはOrderFlowに新しい支払いSDKを統合する必要があります。新しいコンポーネントを統合するたびに@Configurationクラスを書き, Beanを宣言し, プロパティを設定し, 条件付き読み込みを処理する必要があります。チームメンバーのBobはBeanの競合や循環依存で深夜まで作業することが多く, Redisの統合だけで3日かかりました。
(2) 自動設定による解決策
Spring Boot Starterは「コンポーネントの統合」を「依存関係の追加」に簡素化します。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
この依存関係を追加するだけで, Redis接続ファクトリとRedisTemplateが自動的に設定されます。
(3) 成果
AliceがOrderFlowのカスタムStarterを作成した後, 新しいチームメンバーは依存関係を1つ追加するだけで支払いSDKを統合できるようになりました。手動でBeanを設定する必要はなくなり, 統合時間は3日から30分に短縮されました。
3. 自動設定読み込みメカニズム
(1) @EnableAutoConfigurationからAutoConfiguration.importsまで
flowchart LR
A["@EnableAutoConfiguration"] --> B["インポート<br/>AutoConfigurationImportSelector"]
B --> C["読み込み<br/>META-INF/spring/<br/>AutoConfiguration.imports"]
C --> D["@Conditional<br/>アノテーションで<br/>フィルタリング"]
D --> E["条件を満たす<br/>自動設定クラスを<br/>登録"]
| バージョン | 読み込みファイル | 形式 |
|---|---|---|
| Spring Boot 2.x | META-INF/spring.factories |
key=class1,class2 |
| Spring Boot 3.x | META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports |
1行に1つの完全修飾クラス名 |
AutoConfiguration.importsファイルを使用し, 自動設定の登録にspring.factoriesは使用しなくなりました。
(2) 自動設定クラスの本質
自動設定クラスは条件アノテーションを持つ@Configurationクラスです。
(1) ▶ サンプル:DataSource自動設定のソースコードの簡略化
@AutoConfiguration
@ConditionalOnClass(DataSource.class)
@ConditionalOnMissingBean(DataSource.class)
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {
@Bean
@ConfigurationProperties("spring.datasource")
public DataSource dataSource(DataSourceProperties properties) {
return DataSourceBuilder.create()
.url(properties.getUrl())
.username(properties.getUsername())
.password(properties.getPassword())
.build();
}
}
出力:
// 実行成功
4. 条件アノテーションの詳細解説
(1) コア条件アノテーション
| アノテーション | 条件 | 代表的な用途 |
|---|---|---|
@ConditionalOnClass |
指定したクラスがクラスパスに存在する | 依存関係が含まれた後にのみ有効 |
@ConditionalOnMissingClass |
クラスがクラスパスに見つからない | 依存関係がない場合の代替提供 |
@ConditionalOnBean |
指定したBeanがコンテナに存在する | 他のBeanに依存する場合に使用 |
@ConditionalOnMissingBean |
指定したBeanがコンテナに存在しない | デフォルトBeanを提供。ユーザー定義Beanがあれば譲る |
@ConditionalOnProperty |
設定プロパティが条件を満たす | 設定スイッチで機能を制御 |
(1) ▶ サンプル:@ConditionalOnPropertyによるスイッチ制御
@Configuration
@ConditionalOnProperty(
prefix = "orderflow.notification",
name = "enabled",
havingValue = "true",
matchIfMissing = false
)
public class NotificationConfig {
@Bean
public NotificationService emailNotificationService() {
return new EmailNotificationService();
}
}
出力:
// 実行成功
orderflow:
notification:
enabled: true # falseに設定すると通知を無効化
(2) ▶ サンプル:@ConditionalOnMissingBeanによるデフォルト実装の提供
@Configuration
public class OrderFlowAutoConfiguration {
@Bean
@ConditionalOnMissingBean(IdGenerator.class)
public IdGenerator uuidIdGenerator() {
return new UuidIdGenerator();
}
@Bean
@ConditionalOnMissingBean(OrderNumberGenerator.class)
@ConditionalOnProperty(
prefix = "orderflow.order",
name = "number-prefix",
havingValue = "ORD",
matchIfMissing = true
)
public OrderNumberGenerator defaultOrderNumberGenerator() {
return new SequentialOrderNumberGenerator("ORD");
}
}
出力:
// 実行成功
5. カスタムStarter
(1) Starterの命名規則
| タイプ | 命名規則 | 例 |
|---|---|---|
| 公式Starter | spring-boot-starter-* |
spring-boot-starter-web |
| サードパーティStarter | *-spring-boot-starter |
orderflow-spring-boot-starter |
(2) Starterのプロジェクト構造
orderflow-spring-boot-starter/
├── src/main/
│ ├── java/com/orderflow/autoconfigure/
│ │ ├── OrderFlowAutoConfiguration.java
│ │ └── OrderFlowProperties.java
│ └── resources/
│ └── META-INF/spring/
│ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports
└── pom.xml
(1) ▶ サンプル:カスタムStarterの完全なコード
// OrderFlowProperties.java
@ConfigurationProperties(prefix = "orderflow.notification")
public record OrderFlowNotificationProperties(
boolean enabled,
String fromEmail,
String templatePath
) {}
// OrderFlowAutoConfiguration.java
@AutoConfiguration
@ConditionalOnClass(JavaMailSender.class)
@ConditionalOnProperty(
prefix = "orderflow.notification",
name = "enabled",
havingValue = "true"
)
@EnableConfigurationProperties(OrderFlowNotificationProperties.class)
public class OrderFlowAutoConfiguration {
@Bean
@ConditionalOnMissingBean(NotificationService.class)
public NotificationService notificationService(
OrderFlowNotificationProperties props) {
return new EmailNotificationService(
props.fromEmail(),
props.templatePath()
);
}
}
出力:
実行成功
# META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.orderflow.autoconfigure.OrderFlowAutoConfiguration
6. 自動設定のデバッグとトラブルシューティング
(1) --debugモード
起動時に--debugパラメータを追加すると, Spring Bootは自動設定レポートを出力します。
java -jar orderflow-service.jar --debug
(1) ▶ サンプル:自動設定レポートの読み方
============================
CONDITIONS EVALUATION REPORT
============================
Positive matches:
-----------------
DataSourceAutoConfiguration matched:
- @ConditionalOnClass found required class 'javax.sql.DataSource'
Negative matches:
-----------------
ActiveMQAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'javax.jms.ConnectionFactory'
Exclusions:
-----------
None
Unconditional classes:
----------------------
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration
出力:
実行成功
| レポート領域 | 意味 |
|---|---|
| Positive matches | 条件を満たし有効な自動設定 |
| Negative matches | 条件を満たさず無効な自動設定 |
| Exclusions | 明示的に除外された自動設定 |
| Unconditional classes | 無条件で登録される自動設定 |
(2) 自動設定の除外
(2) ▶ サンプル:不要な自動設定の除外
// 方法1:アノテーションによる除外
@SpringBootApplication(exclude = {
DataSourceAutoConfiguration.class,
HibernateJpaAutoConfiguration.class
})
public class OrderFlowApplication { ... }
// 方法2:設定プロパティ
// application.yml
spring:
autoconfigure:
exclude:
- org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
出力:
// 実行成功
| 除外方法 | 適用シナリオ | 柔軟性 |
|---|---|---|
@SpringBootApplication(exclude) |
常に除外する場合 | コンパイル時に決定 |
spring.autoconfigure.exclude |
環境ごとに除外する場合 | 実行時に変更可能 |
@ConditionalOnProperty |
条件で除外する場合 | 最も柔軟 |
7. 総合サンプル:OrderFlow通知Starterの完全な実装
// orderflow-notification-spring-boot-starter
// OrderFlowNotificationProperties.java
package com.orderflow.autoconfigure;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "orderflow.notification")
public record OrderFlowNotificationProperties(
boolean enabled,
String fromEmail,
String templatePath,
SmtpConfig smtp
) {
public record SmtpConfig(String host, int port, boolean ssl) {}
}
// NotificationService.java
package com.orderflow.autoconfigure;
public interface NotificationService {
void send(String to, String subject, String body);
}
// EmailNotificationService.java
package com.orderflow.autoconfigure;
public class EmailNotificationService implements NotificationService {
private final String fromEmail;
private final String templatePath;
public EmailNotificationService(String fromEmail, String templatePath) {
this.fromEmail = fromEmail;
this.templatePath = templatePath;
}
@Override
public void send(String to, String subject, String body) {
// メール送信ロジック
System.out.printf("Send to %s: [%s] %s%n", to, subject, body);
}
}
// OrderFlowNotificationAutoConfiguration.java
package com.orderflow.autoconfigure;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
@AutoConfiguration
@ConditionalOnClass(name = "org.springframework.mail.javamail.JavaMailSender")
@ConditionalOnProperty(prefix = "orderflow.notification", name = "enabled", havingValue = "true")
@EnableConfigurationProperties(OrderFlowNotificationProperties.class)
public class OrderFlowNotificationAutoConfiguration {
@Bean
@ConditionalOnMissingBean(NotificationService.class)
public NotificationService notificationService(OrderFlowNotificationProperties props) {
return new EmailNotificationService(props.fromEmail(), props.templatePath());
}
}
# META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.orderflow.autoconfigure.OrderFlowNotificationAutoConfiguration
❓ よくある質問
📖 まとめ
- Spring Boot 3.xでは
AutoConfiguration.importsファイルを使って自動設定クラスを登録 - 自動設定クラスの核心は条件アノテーション:
@ConditionalOnClass,@ConditionalOnMissingBean,@ConditionalOnProperty @ConditionalOnMissingBeanで「ユーザー定義優先」の原則を実現- カスタムStarterの命名:公式は
spring-boot-starter-*, サードパーティは*-spring-boot-starter --debugモードとActuatorエンドポイントで自動設定レポートを確認可能
📝 練習問題
-
基本問題 (難易度 ⭐):
--debugモードでOrderFlowプロジェクトを起動し, "Positive matches"の自動設定クラスをすべてリストアップし, 各自動設定に必要なクラスパス条件を理解してください。 -
応用問題 (難易度 ⭐⭐):
orderflow-spring-boot-starterを作成し,@ConditionalOnPropertyスイッチで制御される通知機能を含めてください。OrderFlowプロジェクトに統合してテストしてください。 -
チャレンジ問題 (難易度 ⭐⭐⭐):複数実装をサポートする自動設定システムを実装してください。クラスパスにKafkaがあればKafka通知, なければメール通知, どちらもなければログ通知を使用する仕組みにしてください。条件アノテーションの優先度と排他設計について考察してください。



