🧑‍💻 Spring Framework 講座【第11回】アノテーションを卒業!〜Java ConfigによるBeanの定義とカスタマイズ〜

docs

前回までに、Spring Beanの定義には @Component@Service といったアノテーションを使うのが主流だと学びました。これは、私たちが自分で書いたクラスをBeanとして登録する最も簡単な方法です。

しかし、次のような場合は、アノテーションだけでは対応できません。

  1. 外部ライブラリのクラスをBeanとして登録したい場合。(そのクラスのソースコードを書き換えて @Component を付けることができないため)
  2. Beanの生成ロジック初期設定を細かく制御したい場合。

今回は、これらの課題を解決する手段である「Java Config」(Javaコードによる設定)について学びます。


1. Java Configの基本:@Configuration と @Bean

Java Configは、その名の通りJavaコードを使ってBeanを定義する方法で、主に @Configuration@Bean の二つのアノテーションを使用します。

1-1. @Configuration(設定クラス)

@Configuration は、そのクラスが「Beanの定義を行うための設定ファイル」であることをSpringコンテナに伝えるアノテーションです。

このクラス自体も、SpringコンテナによってBeanとして管理されます。

1-2. @Bean(Bean定義メソッド)

@Configuration クラス内のメソッドに @Bean を付けると、そのメソッドが返したオブジェクトがSpringコンテナにBeanとして登録されます。

Java

// Springの設定ファイルとして扱う
@Configuration 
public class AppConfig {

    // ① @Beanを付けたメソッドが、Beanを生成し、返却する
    @Bean
    public MySystemConfig systemConfig() {
        // newを使ってオブジェクトを生成し、初期設定を行う
        MySystemConfig config = new MySystemConfig();
        config.setAppName("業務管理システム");
        config.setMaxConnections(50);
        return config; // この MySystemConfig オブジェクトがBeanとして登録される
    }
}

これで、MySystemConfig というBeanがコンテナに登録され、他のServiceクラスなどで @Autowired により注入して使えるようになります。


2. 外部ライブラリのBean登録

Java Configが最も威力を発揮するのは、外部ライブラリのクラスをBeanとして使いたい場合です。

例えば、java.time パッケージの Clock クラス(時刻を扱う標準クラス)を特定の要件で設定して使いたいとします。Clock クラスには @Component を付けられません。

Java

import java.time.Clock;

@Configuration
public class TimeConfig {

    @Bean
    public Clock fixedClock() {
        // システムの現在時刻ではなく、固定時刻を返すClockをBeanとして登録
        return Clock.systemUTC(); 
    }
    
    // 他のクラスでこのClock Beanを利用する
}

これで、Clock 型が必要な場所に、常に fixedClock が注入されるようになります。


3. DIの活用:@Bean メソッド間の連携

@Configuration クラスの内部にある @Bean メソッドは、他の @Bean メソッドを呼び出すことができます。この際、Springは呼び出し側のメソッドに、すでにコンテナに登録されているBeanを渡してくれます。

これにより、Bean間の依存関係をJavaコードで明確に記述できます。

Java

// Loggerインターフェースと実装クラスがあると仮定
interface Logger { void log(String msg); }
class ConsoleLogger implements Logger { /* ... 実装省略 ... */ }

@Configuration
public class ServiceConfig {

    // ① Logger Bean を定義
    @Bean
    public Logger consoleLogger() {
        return new ConsoleLogger(); 
    }

    // ② UserService Bean を定義する際に、Logger Beanに依存させる
    // メソッドの引数に Logger Bean を要求するだけで、Springが自動で注入する
    @Bean
    public UserService userService(Logger consoleLogger) {
        // newでUserServiceを生成し、初期設定でLoggerを渡す
        return new UserService(consoleLogger); 
    }
    
    // UserService クラスのコンストラクタは以下のようになっていると想定
    // public UserService(Logger logger) { this.logger = logger; }
}

このように、@Bean メソッドの引数として別のBeanを指定することで、コンテナ内の依存関係を構築できます。これは、アノテーションによるDI(@Autowired)と並ぶ、SpringのDIの主要な手段です。


4. アノテーション vs Java Config

どちらの方法を使うべきか迷うかもしれませんが、一般的なルールは以下の通りです。

特徴アノテーションベース (@Serviceなど)Java Config (@Configuration + @Bean)
対象自分でソースコードが書けるクラス外部ライブラリのクラスや、生成ロジックが複雑なクラス
記述形式クラスに印を付けるだけJavaコードで生成ロジックを記述
主流度Spring Bootでは最も主流特定のカスタマイズが必要な場合に利用

業務開発では、自作クラスはアノテーション、特別な設定や外部ライブラリは Java Config と、両者を併用するのが一般的です。

✅ 本日のまとめ

  • Java Configは、Beanの生成ロジックを細かく制御したり、外部ライブラリのクラスをBeanとして登録したりする際に使う。
  • @Configuration は設定クラスであることを示し、このクラス内でBean定義を行う。
  • @Bean が付いたメソッドは、その戻り値をBeanとしてコンテナに登録する。
  • @Bean メソッドの引数として他のBeanを指定することで、依存関係を構築できる。

🔔 次回予告

これでSpring Coreの核となる知識はほぼ網羅しました。次回は、Beanの定義や設定ファイルにおいて、Javaコードではなく「文字列」として記述できる便利な仕組み、SpEL (Spring Expression Language) について学びます。これは、プロパティファイルの値や、他のBeanのメソッドの結果を参照したい場合に非常に強力な機能です。

次回:【第12回】Spring Expression Language (SpEL) の活用 にご期待ください!

コメント

タイトルとURLをコピーしました