1.概要

Spring 2.5以降、このフレームワークは

@ Autowired

Annotationsによって駆動される新しいスタイルのDependency Injectionを導入しました。このアノテーションは、SpringがコラボレーションBeanを解決してあなたのBeanに注入することを可能にします。

このチュートリアルでは、自動配線を有効にする方法、さまざまな方法でBeanを配線する方法、Beanをオプションにする方法、および@ @ Qualifier__アノテーションを使用してBeanの競合を解決する方法について説明します。

2.

@ Autowired

アノテーションを有効にする

アプリケーションでJavaベースの設定を使用している場合は、

AnnotationConfigApplicationContext

を使用して以下のようにSpring設定を読み込むことで、アノテーションドリブンインジェクションを有効にできます。

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

別の方法として、Spring XMLでは、次のようにSpring XMLファイルで宣言することで有効にできます。

3.

@ Autowired

を使う

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


3.1. プロパティの

@ Autowired


注釈はプロパティに直接使用できるため、ゲッターやセッターは不要になります。

@Component("fooFormatter")
public class FooFormatter {

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

@Component
public class FooService {

    @Autowired
    private FooFormatter fooFormatter;

}

上記の例では、Springは

FooService

が作成されたときに

fooFormatter

を探して注入します。


3.2. Settersの

@ Autowired



@ Autowired

アノテーションは設定メソッドで使うことができます。以下の例では、アノテーションがsetterメソッドで使用されると、

FooService

が作成されたときに、setFetFormatter__のインスタンスで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とOptionalの依存関係

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;

}


@ Qualifier

を特定の実装の名前(この場合は

fooFormatter

)で指定することで、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";
    }
}

実装に注釈が付けられると、カスタムQualifier注釈は以下のように使用できます。

@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を絞り込むことができますが、自動配線は実際にはタイプ別のインジェクションに関するものであり、これがこのコンテナー機能の最適な使用方法です。

このチュートリアルのソースコードはhttps://github.com/eugenp/tutorials/tree/master/spring-all[GitHubプロジェクト]にあります。これはEclipseベースのプロジェクトなので、インポートするのは簡単ですし、そのまま実行します。