Spring @Qualifierアノテーション

1. 概要

この記事では、_ @ Qualifier_アノテーションが私たちを助けることができるもの*、それが解決する問題、およびその使用方法を探ります。
また、_ @ Primary_アノテーションとの違いや、名前による自動配線との違いについても説明します。

2. 明確化のための自動配線の必要性

link:/spring-autowire[_@Autowired_]アノテーションは、Springで依存関係を明示的に挿入する必要性を高める素晴らしい方法です。 また、有用ではありますが、SpringがどのBeanを注入するかを理解するには、このアノテーションだけでは不十分なユースケースがあります。
デフォルトでは、Springはタイプごとに自動配線されたエントリを解決します。
**コンテナで同じタイプの複数のBeanが使用可能な場合、フレームワークは_NoUniqueBeanDefinitionException _ ** __、__をスローし、複数のBeanが自動配線に使用可能であることを示します。
特定のインスタンスでSpringがBeanコラボレーターとして注入する可能性のある2つの候補が存在する状況を想像してみましょう。
@Component("fooFormatter")
public class FooFormatter implements Formatter {

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

@Component("barFormatter")
public class BarFormatter implements Formatter {

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

@Component
public class FooService {

    @Autowired
    private Formatter formatter;
}
_FooService_をコンテキストにロードしようとすると、Springフレームワークは_NoUniqueBeanDefinitionException_をスローします。 これは、* SpringがどのBeanを注入するかを認識していないためです*。 この問題を回避するには、いくつかの解決策があります。 _ @ Qualifier_アノテーションはその1つです。

3. _ @ Qualifier_注釈

_ @ Qualifier_アノテーションを使用することで、どのBeanを注入する必要があるかという問題を排除できます*。
前の例をもう一度見て、使用するBeanを示す_ @ Qualifier_アノテーションを含めることで問題を解決する方法を見てみましょう。
public class FooService {

    @Autowired
    @Qualifier("fooFormatter")
    private Formatter formatter;
}
使用する特定の実装の名前とともに_ @ Qualifier_アノテーションを含めることにより(この例では_Foo_)、Springが同じタイプの複数のBeanを検出する際のあいまいさを回避できます。
使用する修飾子の名前が_ @ Component_アノテーションで宣言されているものであることを考慮する必要があります。
同じ効果を得るために、_ @ Component_アノテーションで名前を指定する代わりに、_Formatter_実装クラスで_ @ Qualifier_アノテーションを使用することもできます。
@Component
@Qualifier("fooFormatter")
public class FooFormatter implements Formatter {
    //...
}

@Component
@Qualifier("barFormatter")
public class BarFormatter implements Formatter {
    //...
}

4. _ @ Qualifier_ vs _ @ Primary_

link:/spring-primary[_@Primary_]と呼ばれる別の注釈があります。これは、依存性注入に関してあいまいさが存在する場合に、注入するBeanを決定するために使用できます。
この注釈は、*同じタイプの複数のBeanが存在する場合の設定を定義します*。 特に指定がない限り、_ @ Primary_アノテーションに関連付けられたBeanが使用されます。
例を見てみましょう。
@Configuration
public class Config {

    @Bean
    public Employee johnEmployee() {
        return new Employee("John");
    }

    @Bean
    @Primary
    public Employee tonyEmployee() {
        return new Employee("Tony");
    }
}
この例では、両方のメソッドが同じ_Employee_型を返します。 Springが注入するBeanは、メソッド_tonyEmployee_によって返されるBeanです。 これは、_ @ Primary_注釈が含まれているためです。 このアノテーションは、特定のタイプのどのBeanをデフォルトで注入するかを指定したいときに便利です*。
また、ある注入ポイントで他のBeanが必要な場合は、具体的に示す必要があります。 _ @ Qualifier_アノテーションを使用してそれを行うことができます。 たとえば、_ @ Qualifier_アノテーションを使用して、_johnEmployee_メソッドによって返されたBeanを使用するように指定できます。
  • _ @ Qualifier_と_ @ Primary_の両方の注釈が存在する場合、_ @ Qualifier_注釈が優先されることに注意してください。

    _ @ Primary_アノテーションを使用する別の方法を見てみましょう。今回は最初の例を使用します。
@Component
@Primary
public class FooFormatter implements Formatter {
    //...
}

@Component
public class BarFormatter implements Formatter {
    //...
}
*この場合、_ @ Primary_アノテーションは実装クラスの1つに配置され*、シナリオを明確にします。

5. _ @ Qualifier_と名前による自動配線

自動配線時に複数のBeanを決定する別の方法は、注入するフィールドの名前を使用することです。 *これは、Springに他のヒントがない場合のデフォルトです*。 最初の例に基づいたコードを見てみましょう。
public class FooService {

    @Autowired
    private Formatter fooFormatter;
}
この場合、フィールド名はそのBeanの_ @ Component_アノテーションで使用した値と一致するため、Springは注入するBeanが_FooFormatter_であると判断します。

6. 結論

どのBeanを注入するかを明確にする必要があるシナリオについて説明しました。 特に、_ @ Qualifier_アノテーションについて説明し、使用する必要があるBeanを決定する他の同様の方法と比較しました。
いつものように、この記事の完全なコードはhttps://github.com/eugenp/tutorials/tree/master/spring-di[GitHubで]から入手できます。