Dev Study
← Spring コース

41. XML・アノテーション・JavaConfig

に「どのを作り、誰に誰を渡すか」というの書き方のうち、3通りを扱います。XML の bean 要素(1.0 より前からある)、 と (2.5、2007年)、 クラスの (3.0、2009年)です。同じ2つの部品をそれぞれで配線すると、 7.0.9 と 25 で結果は同じでした。

移ったのは配線の情報の置き場所です。XML では業務クラスに Spring の が無く、情報は別ファイルにあります。では情報がクラス自身に付き、まとめて書く場所は消えます。 は情報をクラスの外に置いたまま Java で書くので、new に渡す型の食い違いはコンパイル時に分かります。ただし @Bean メソッドの引数は Spring が起動時に型で探して渡すので、無ければ起動時に失敗します。

「XML は廃止された」は誤りで、この実験では警告も出ずに動きました。「2.5 で初めてアノテーションが入った」も正確ではありません。当時のリファレンスによれば 2.0 に などが既にあり、2.5 で @Autowired と自動検出がそろいました。JavaConfig も 3.0 より前から別プロジェクトとして存在していました。新規のコードでどの書き方が多いかは、このコースでは測っていません。

点線の付いた語はタップすると説明が出ます。用語集を開く →

同じ配線の3通り — 配線の情報がどこにあるか
XML(1.0 より前から)情報は beans.xml に。クラスは Spring を知らない
アノテーション(2.5 / 2007年)情報はクラス自身に。配線を書いた場所は無い
JavaConfig(3.0 / 2009年)情報は設定クラスに。クラスは Spring を知らない
Spring Framework 7.0.9 が読み取って組み立てる
GreetingService ← MessageRepository3通りとも同じ結果(hello)を出力
  • ・XML による Bean 定義は 1.0 より前からあり、0.9(2003年6月)の changelog に revised bean definition XML format with DTD とあります
  • ・現行リファレンスは、ここで扱う3通りのほかに Groovy スクリプトも挙げています
  • ・Bean の名前は、XML では id、自動検出ではクラス名の先頭を小文字にしたもの、@Bean ではメソッド名になりました
  • ・アノテーションと JavaConfig では、アノテーションを処理するための内部の Bean が4つ、利用者の Bean とは別に登録されていました

サンプルコード(フレームワーク環境が必要なため表示のみ)

// JavaConfig — 配線を Java のメソッドで書く。
// (実験では AppConfig と JavaConfigMain は別ファイル。ここでは1つにまとめ、
//  package 文と一部の import を省いている)
// MessageRepository と GreetingService は Spring の import を持たない素のクラス
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {
    @Bean
    public MessageRepository messageRepository() {
        return new MessageRepository();
    }

    @Bean
    public GreetingService greetingService(MessageRepository messageRepository) {
        // new に渡す型が合わなければコンパイルで止まる。
        // 引数に渡す Bean が見つからない場合は、起動時に例外になる
        return new GreetingService(messageRepository);
    }
}

class JavaConfigMain {
    public static void main(String[] args) {
        try (var ctx = new AnnotationConfigApplicationContext(AppConfig.class)) {
            System.out.println("[javaconfig] " + ctx.getBean(GreetingService.class).greet());
            System.out.println("[javaconfig] beans = " + String.join(", ", ctx.getBeanDefinitionNames()));
        }
    }
}

// Spring Framework 7.0.9 / JDK 25 での出力
// (実験の greet() は repository の識別番号も付けて返す。
//  @ の後ろの数値は実行のたびに変わる。beans の先頭にある内部の Bean 4つは ... で省略)
// [javaconfig] hello (repository@1926343982)
// [javaconfig] beans = ..., appConfig, messageRepository, greetingService
//
// Bean の名前はメソッド名から付いた。設定クラス自身(appConfig)も Bean になっている

図やコードに出てくる用語(タップで説明)

サンプルコードで身につける(5本) →

学んだ概念を、素朴な例から実務寄りの例まで5つの具体例で確認します。

公式ドキュメントで詳しく ↗