Dev Study
← 解説「XML・アノテーション・JavaConfig」に戻る

サンプルコードで身につける: XML・アノテーション・JavaConfig

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

1出発点: 素の Java で手で配線する

を使わずに、2つのを の中で作ってつなぐ例です。とは「どのクラスを作り、誰に誰を渡すか」のことで、ここでは new の2行がそれに当たります。以降の3通りは、この2行の情報をどこに書くかの違いです。

Java

2XML で配線する(1.0 より前からある書き方)

配線を に書いた版です。bean 要素の class がどのクラスを作るか、constructor-arg の ref が誰を渡すかを表し、業務クラスには Spring の がありません。この XML は 7.0.9 と 25 で、警告なしに動きました。

beans.xml設定ファイル
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
 
<bean id="messageRepository" class="demo.plain.MessageRepository"/>
 
<bean id="greetingService" class="demo.plain.GreetingService">
<constructor-arg ref="messageRepository"/>
</bean>
 
</beans>
import demo.plain.GreetingService;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class XmlMain {
    public static void main(String[] args) {
        // クラスパス上の beans.xml を読んでコンテナを作る
        try (var ctx = new ClassPathXmlApplicationContext("beans.xml")) {
            System.out.println("[xml]        " + ctx.getBean(GreetingService.class).greet());
            System.out.println("[xml]        beans = " + String.join(", ", ctx.getBeanDefinitionNames()));
        }
    }
}

3アノテーションで配線する(2.5 の書き方)

クラスに を付け、に を付けた版です。起動側は名を渡すだけで、Spring がその下のクラスを探して組み立てるので、配線をまとめて書いた場所はどこにもありません。現行の版では、コンストラクタが1つなら @Autowired は省略できます。

// demo/anno/MessageRepository.java
@Component
public class MessageRepository {
    public String find() { return "hello"; }
}

// demo/anno/GreetingService.java
@Component
public class GreetingService {
    private final MessageRepository repository;

    @Autowired
    public GreetingService(MessageRepository repository) {
        this.repository = repository;
    }
    // greet() は省略
}

// demo/AnnotationMain.java
public class AnnotationMain {
    public static void main(String[] args) {
        // "demo.anno" パッケージの下を探してもらう
        try (var ctx = new AnnotationConfigApplicationContext("demo.anno")) {
            System.out.println("[annotation] " + ctx.getBean(GreetingService.class).greet());
        }
    }
}

// import は org.springframework.stereotype.Component と
// org.springframework.beans.factory.annotation.Autowired。
// 業務クラスが Spring の型に依存するようになった点が XML との違い

43通りを動かした出力を並べる

同じ2つの部品を3通りで配線し、Spring Framework 7.0.9 と JDK 25 で動かした出力です(@ の後ろの数値は実行のたびに変わります)。XML では登録された は自分で書いた2つだけですが、残りの2つでは internal を含む名前の Bean が4つ先に並びます。を処理する役を、が自分で登録しているためです。

3つの main を順に実行(Spring Framework 7.0.9 / JDK 25)コマンド出力
$ java -cp 'out:lib/*' demo.XmlMain
[xml] hello (repository@1335505684)
[xml] beans = messageRepository, greetingService
$ java -cp 'out:lib/*' demo.AnnotationMain
[annotation] hello (repository@282821294)
[annotation] beans = org.springframework.context.annotation.internalConfigurationAnnotationProcessor, org.springframework.context.annotation.internalAutowiredAnnotationProcessor, org.springframework.context.event.internalEventListenerProcessor, org.springframework.context.event.internalEventListenerFactory, greetingService, messageRepository
$ java -cp 'out:lib/*' demo.JavaConfigMain
[javaconfig] hello (repository@1926343982)
[javaconfig] beans = org.springframework.context.annotation.internalConfigurationAnnotationProcessor, org.springframework.context.annotation.internalAutowiredAnnotationProcessor, org.springframework.context.event.internalEventListenerProcessor, org.springframework.context.event.internalEventListenerFactory, appConfig, messageRepository, greetingService

53通りの比較表

3つの書き方を、確かめられた版と配線の情報の置き場所で並べました(日付は各版の告知のもの)。XML による定義は 1.0 より前からあり、0.9(2003年6月)の changelog に既に出てきます。アノテーションだけが業務クラスに Spring の import を持ち込み、 は別プロジェクトとして存在したものが 3.0 で本体に入りました。

配線の書き方と、情報の置き場所表
書き方 | 確かめた版 | 告知の日付 | 配線の情報がある場所 | 業務クラスの Spring への依存
---------------+------------+-------------+-------------------------------+-----------------------------
XML | 1.0 に既出 | 2004-03-24 | beans.xml | なし
アノテーション | 2.5 | 2007-11-19 | それぞれのクラスに付けた印 | あり
JavaConfig | 3.0 | 2009-12-16 | @Configuration を付けたクラス | なし

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