春のガイド@Autowired

Spring @Autowiredガイド

1. 概要

Spring 2.5以降、フレームワークは@Autowiredアノテーションによって駆動される新しいスタイルの依存性注入を導入しました。 このアノテーションにより、SpringはコラボレーションBeanを解決してBeanに注入できます。

このチュートリアルでは、自動配線,のさまざまな ways to wire in beans_ making beans optional, resolving bean conflicts using _@Qualifier注釈を有効にする方法と、潜在的な例外シナリオについて説明します。

参考文献:

スプリングコンポーネントスキャン

Springコンポーネントスキャンの背後にあるメカニズムと、独自のニーズに合わせて微調整する方法について学習します。

Springでの制御の反転と依存性注入の概要

Inversion of Control and Dependency Injectionの概念の簡単な紹介に続いて、Spring Frameworkを使用した簡単なデモンストレーション

2. @Autowired注釈の有効化

アプリケーションでJavaベースの構成を使用している場合は、AnnotationConfigApplicationContextを使用して以下のようにSpring構成をロードすることにより、アノテーション駆動型インジェクションを有効にできます。

@Configuration
@ComponentScan("com.example.autowire.sample")
public class AppConfig {}

別の方法として、Spring XMLでは、次のようにSpring XMLファイルで宣言することで有効にできます:<context:annotation-config/>

3. @Autowiredの使用

注釈の挿入を有効にすると、プロパティ、セッター、およびコンストラクターで自動配線を使用できます。

3.1. プロパティの@Autowired

アノテーションはプロパティで直接使用できるため、ゲッターとセッターの必要性がなくなります。

@Component("fooFormatter")
public class FooFormatter {

    public String format() {
        return "foo";
    }
}
@Component
public class FooService {

    @Autowired
    private FooFormatter fooFormatter;

}

上記の例では、FooServiceが作成されると、SpringはfooFormatterを検索して挿入します。

3.2. セッターの@Autowired

@Autowiredアノテーションは、setterメソッドで使用できます。 以下の例では、setterメソッドでアノテーションが使用されている場合、FooServiceが作成されるときに、FooFormatterのインスタンスを使用してsetterメソッドが呼び出されます。

public class FooService {

    private FooFormatter fooFormatter;

    @Autowired
    public void setFooFormatter(FooFormatter fooFormatter) {
            this.fooFormatter = fooFormatter;
    }
}

3.3. コンストラクターの@Autowired

@Autowiredアノテーションは、コンストラクターでも使用できます。 以下の例では、アノテーションがコンストラクターで使用される場合、FooServiceが作成されるときに、FooFormatterのインスタンスがコンストラクターへの引数として挿入されます。

public class FooService {

    private FooFormatter fooFormatter;

    @Autowired
    public FooService(FooFormatter fooFormatter) {
        this.fooFormatter = fooFormatter;
    }
}

4. @Autowiredおよびオプションの依存関係

Springは、依存Beanが構築されているときに@Autowired依存関係が使用可能であることを期待しています。 フレームワークが配線用のBeanを解決できない場合、引用符で囲まれていない例外がスローされ、Springコンテナが正常に起動できなくなります。

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [com.autowire.sample.FooDAO] found for dependency:
expected at least 1 bean which qualifies as autowire candidate for this dependency.
Dependency annotations:
{@org.springframework.beans.factory.annotation.Autowired(required=true)}

これを回避するには、以下のようにBeanをオプションで指定できます。

public class FooService {

    @Autowired(required = false)
    private FooDAO dataAccessor;

}

5. オートワイヤの明確化

デフォルトでは、Springは@Autowiredエントリをタイプ別に解決します。 コンテナで同じタイプの複数のBeanが使用可能な場合、フレームワークは、複数のBeanが自動配線に使用できることを示す致命的な例外をスローします。

5.1. @Qualifierによる自動配線

@Qualifierアノテーションを使用して、必要なBeanを示唆および絞り込むことができます。

@Component("fooFormatter")
public class FooFormatter implements Formatter {

    public String format() {
        return "foo";
    }
}
@Component("barFormatter")
public class BarFormatter implements Formatter {

    public String format() {
        return "bar";
    }
}
public class FooService {

    @Autowired
    private Formatter formatter;

}

Springコンテナが注入できるFormatterの具体的な実装は2つあるため、SpringはFooServiceを作成するときにNoUniqueBeanDefinitionException例外をスローします。

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type [com.autowire.sample.Formatter] is defined:
expected single matching bean but found 2: barFormatter,fooFormatter

これは、@Qualifierアノテーションを使用して実装を絞り込むことで回避できます。

public class FooService {

    @Autowired
    @Qualifier("fooFormatter")
    private Formatter formatter;

}

特定の実装の名前(この場合はfooFormatter)で@Qualifierを指定することにより、Springが同じタイプの複数のBeanを検出したときのあいまいさを回避できます。

@Qualifierアノテーションの値は、FooFormatter実装の@Componentアノテーションで宣言された名前と一致することに注意してください。

5.2. カスタム修飾子による自動配線

Springを使用すると、独自の@Qualifierアノテーションを作成できます。 カスタム修飾子を作成するには、注釈を定義し、以下のように定義内に@Qualifier注釈を指定します。

@Qualifier
@Target({
  ElementType.FIELD, ElementType.METHOD, ElementType.TYPE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface FormatterType {

    String value();

}

定義すると、FormatterTypeをさまざまな実装内で使用して、カスタム値を指定できます。

@FormatterType("Foo")
@Component
public class FooFormatter implements Formatter {

    public String format() {
        return "foo";
    }
}
@FormatterType("Bar")
@Component
public class BarFormatter implements Formatter {

    public String format() {
        return "bar";
    }
}

実装に注釈を付けたら、カスタム修飾子注釈を次のように使用できます。

@Component
public class FooService {

    @Autowired
    @FormatterType("Foo")
    private Formatter formatter;

}

@Targetアノテーションで指定された値は、修飾子を使用して注入ポイントをマークできる場所を制限します。

上記のコードスニペットでは、修飾子を使用して、Springがフィールド、メソッド、タイプ、およびパラメーターにBeanを注入できるポイントを明確にすることができます。

5.3. 名前による自動配線

フォールバックとして、SpringはBean名をデフォルトの修飾子値として使用します。

したがって、Beanプロパティ名を定義することにより、この場合はfooFormatter,としてSpringはそれをFooFormatter実装に一致させ、FooServiceが構築されるときにその特定の実装を注入します。

public class FooService {

    @Autowired
    private Formatter fooFormatter;

}

6. 結論

@QualifierとBean名のフォールバック一致の両方を使用して、特定のBeanに絞り込むことができますが、自動配線は実際にはタイプごとの注入に関するものであり、これがこのコンテナー機能の最適な使用方法です。

このチュートリアルのソースコードはthe GitHub projectにあります。これはEclipseベースのプロジェクトであるため、そのままインポートして実行するのは簡単です。