Upgrade to Pro — share decks privately, control downloads, hide ads and more …

作って学ぶSpring BootのAuto Configuration / JJUG Nigh...

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers. →

作って学ぶSpring BootのAuto Configuration / JJUG Night Seminar 2026-10-19

Avatar for Ryo Shindo

Ryo Shindo

October 19, 2026

More Decks by Ryo Shindo

Other Decks in Programming

Transcript

  1. 本セッションの目的  "黒魔術"と呼ばれがちなSpring BootのAuto Configurationの 仕組みを理解する  Spring Boot初学者やなんとなく使っている人向けです 

    Bean登録がよく分からない人  Starterを追加するだけで機能が使える理由が分からない人  Auto Configurationという言葉は知っているけれど、仕組みはよく 分からない人
  2. Dependency Injection (DI)とは  日本語にすると「依存性の注入」  単純に言うと依存オブジェクトをクラス内でnewせず クラスの外から受け取る仕組みのこと  SpringのDI対象となるオブジェクトのことを

    "Spring Bean"と呼ぶ @Service public class NotificationService { DIコンテナ (ApplicationContext) private final JdbcClient jdbcClient; public NotificationService(JdbcClient jdbcClient) { this.jdbcClient = jdbcClient; } } JdbcClientオブジェクトを インジェクション
  3. @ComponentによるBean登録  コンポーネントスキャン対象であれば、クラスに@Componentを つけるだけで自動的にDIコンテナにBean登録される @Component public class SystemDateTimeProvider { public

    LocalDateTime now() { return LocalDateTime.now(); } } @Service, @Repositoryなどの アノテーションでもBean登録できる @Service public class NotificationService { private final SystemDateTimeProvider systemDateTimeProvider; public NotificationService(SystemDateTimeProvider systemDateTimeProvider) { this.systemDateTimeProvider = systemDateTimeProvider; } }
  4. コンポーネントスキャン  Spring Bootではデフォルトでは@SpringBootApplication以下の階層の パッケージにある@Componentなどがつけられたクラスを 自動的にスキャンしてBean登録する package com.foo; @Service public

    class FooService { } package com.foo; @SpringBootApplication public class FooApplication { static void main(String[] args) { SpringApplication.run( FooApplication.class, args); } } スキャンOK package com.foo.bar; @Service public class BarService { } スキャンしない package com.baz; @Service public class BazService { }
  5. 固定日時を返す実装の追加 public interface DateTimeProvider { LocalDateTime now(); } インタフェースの抽出 @Component

    public class SystemDateTimeProvider implements DateTimeProvider { @Override public LocalDateTime now() { return LocalDateTime.now(); } } public class FixedDateTimeProvider implements DateTimeProvider { @Override public LocalDateTime now() { return LocalDateTime.of(2026, 10, 19, 19, 0, 0, 0); } }
  6. Beanをどう切り替える?  2つのBeanの両方に@Componentをつける場合(=両方Bean登録する)、 依存元全てで次のようなif文が必要になる public NotificationService(@Value("${app.datetime.type}") String type, SystemDateTimeProvider systemDateTimeProvider,

    FixedDateTimeProvider fixedDateTimeProvider) { if (type != null && type.equalsIgnoreCase("fixed")) { this.dateTimeProvider = fixedDateTimeProvider; 冗長 } else { 依存が増えてる this.dateTimeProvider = systemDateTimeProvider; } } public NotificationService(DateTimeProvider dateTimeProvider) { this.dateTimeProvider = dateTimeProvider; このままだと } Bean重複で起動時にエラー
  7. @BeanによるBean登録  @Configurationをつけたクラス内で、@Beanをつけたファクトリメソッドを 作成することでBean登録が可能  メソッドの中で条件分岐することで実装を切り替えることができる @Configuration public class DateTimeConfiguration

    { @Bean public DateTimeProvider dateTimeProvider(@Value("${app.datetime.type}") String type) { if (type != null && type.equalsIgnoreCase("fixed")) { return new FixedDateTimeProvider(); } else { プロパティで実装を切り替え return new SystemDateTimeProvider(); } } } ※Configurationのクラスもコンポーネントスキャン対象のパッケージに置くか、 @Importで明示的にインポートする必要がある(後述)
  8. Auto Configurationの作り方 ① @Configurationを@AutoConfigurationに変更する ※必須ではないけど推奨 • Auto Configurationであることが明確に分かるようになるほか、 他のAuto Configurationと比べた適用順序を属性で指定できるといった

    メリットがある @AutoConfiguration public class DateTimeConfiguration { @Bean public DateTimeProvider dateTimeProvider(@Value("${app.datetime.type}") String type) { if (type != null && type.equalsIgnoreCase("fixed")) { return new FixedDateTimeProvider(); } else { return new SystemDateTimeProvider(); } } }
  9. Auto Configurationの作り方 ③ Spring Bootアプリを起動すると、次のようなデバッグログ が出力される 2026-10-14T21:32:32.887+09:00 DEBUG 77292 ---

    [hoge-project] [main] .s.b.a.l.ConditionEvaluationReportLogger : ============================ CONDITIONS EVALUATION REPORT ============================ (中略) Unconditional classes: ---------------------- io.github.rshindo.library.DateTimeConfiguration ….
  10. @ConditionalOnProperty  プロパティの値ごとにBeanを切り替えることができる app.datetime.type=fixed の場合にマッチする @AutoConfiguration public class DateTimeConfiguration {

    @Bean @ConditionalOnProperty(name = "app.datetime.type", havingValue = "fixed") public DateTimeProvider fixedDateTimeProvider() { return new FixedDateTimeProvider(); } @Bean @ConditionalOnProperty(name = "app.datetime.type", havingValue = "system", matchIfMissing = true) public DateTimeProvider systemDateTimeProvider() { return new SystemDateTimeProvider(); app.datetime.type=system または } プロパティキーがない場合にマッチする } ※ただし空文字はマッチしない
  11. @ConditionalOnMissingBean  他に有効なBeanがない場合に有効になる(つまりデフォルト)  アプリ側のBean定義を優先したい場合にも使える @AutoConfiguration public class DateTimeConfiguration {

    @Bean @ConditionalOnProperty(name = "app.datetime.type", havingValue = "fixed") public DateTimeProvider fixedDateTimeProvider() { return new FixedDateTimeProvider(); 他のBeanがない場合のデフォルトになる } @Bean @ConditionalOnMissingBean(DateTimeProvider.class) public DateTimeProvider systemDateTimeProvider() { return new SystemDateTimeProvider(); } }
  12. Tips  @ConditionalOn〜 はクラスにもつけられる @AutoConfiguration JdbcClientのBeanがある場合のみ有効 @ConditionalOnBean(JdbcClient.class) public class InvoiceRepositoryConfiguration

    { … }  @ConditionalOnMissingBeanは基本的にはクラスレベルでつけておくか、 全てのBeanメソッドにつける  アプリ側のBean登録が優先されないと、カスタマイズ性が悪くて 使いづらいライブラリになるぞ!
  13. Auto Configurationを読んでみよう!  ここまでの知識でSpring Bootが提供しているAuto Configurationのコードを読むことができる  ほとんどが@ConditionalOn〜と@Importの組み合わせ  (例)

    spring-boot-starter-jdbc のJdbcClientのBean定義 @AutoConfiguration(after = JdbcTemplateAutoConfiguration.class) @ConditionalOnSingleCandidate(NamedParameterJdbcTemplate.class) @ConditionalOnMissingBean(JdbcClient.class) @Import(DatabaseInitializationDependencyConfigurer.class) public final class JdbcClientAutoConfiguration { @Bean JdbcClient jdbcClient(NamedParameterJdbcTemplate jdbcTemplate) { return JdbcClient.create(jdbcTemplate); } }
  14. Auto Configurationを読んでみよう!  どこにBean定義があるか見つからないときの手段として、 Actuatorのconditionsエンドポイントで調べることができる { "contexts": { "hoge-project": {

    "negativeMatches": { "DateTimeConfiguration#fixedDateTimeProvider": { "notMatched": [ { "condition": "OnPropertyCondition", "message": "@ConditionalOnProperty (app.datetime.type=fixed) found different value in property 'app.datetime.type'" } ], "matched": [] },