春のガイド@Autowired
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ベースのプロジェクトなので、インポートするのは簡単ですし、そのまま実行します。