1. 概述
在本文中,我们将探索@Qualifier注释可以帮助我们做什么,它解决了哪些问题,以及如何使用它。
我们还将解释它与@Primary注释和名称自动装配的区别。
2. Autowire需要明确的Bean
@Autowired 注解是一种很好的方式,可以显式地将依赖注入到Spring中。尽管它很有用,但在某些情况下,仅此注释不足以让Spring理解注入哪个bean。
默认情况下,Spring根据类型解析自动加载条目。
如果容器中有多个相同类型的bean可用,框架将抛出NoUniqueBeanDefinitionException,表示有多个bean可用于自动装配。
让我们想象这样一种情况:在给定的实例中,存在两个可能的候选者,可以让Spring作为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"; }} @Componentpublic class FooService { @Autowired private Formatter formatter;}
3. @Qualifier注解
通过使用@Qualifier注解,我们可以消除需要注入哪个bean的问题。
让我们回顾之前的例子,看看我们是如何通过包含@Qualifier注解来指出我们想使用哪个bean来解决这个问题的:
public class FooService { @Autowired @Qualifier("fooFormatter") private Formatter formatter;}
通过将@Qualifier注释与我们想要使用的特定实现的名称(在本例中为Foo)一起包含,我们可以避免在Spring发现相同类型的多个bean时出现歧义。
我们需要考虑使用的限定符名称是在@Component注释中声明的。
注意,我们也可以在实现类的Formatter上使用@Qualifier注释,而不是在它们的@Component注释中指定名称,以获得相同的效果:
@Component@Qualifier("fooFormatter")public class FooFormatter implements Formatter { //...} @Component@Qualifier("barFormatter")public class BarFormatter implements Formatter { //...}
4. @Qualifier和@Primary对比
还有另一个名为@Primary的注释,我们可以使用它来决定在依赖项注入出现歧义时注入哪个bean。
当存在多个相同类型的bean时,该注释定义首选项。除非另有指示,否则将使用与@Primary注释关联的bean。
示例如下:
@Configurationpublic class Config { @Bean public Employee johnEmployee() { return new Employee("John"); } @Bean @Primary public Employee tonyEmployee() { return new Employee("Tony"); }}
在本例中,这两个方法返回相同的雇员类型。Spring将注入的bean就是tonyEmployee方法返回的bean。这是因为它包含@Primary注释。当我们想要指定默认情况下应该注入特定类型的哪个bean时,这个注释非常有用。
如果我们在某个注入点需要另一个bean,我们需要特别指出它。我们可以通过@Qualifier注释来做到这一点。例如,我们可以通过使用@Qualifier注释来指定我们想要使用johnEmployee方法返回的bean。
值得注意的是,如果@Qualifier和@Primary注释同时存在,那么@Qualifier注释将具有优先级。基本上,@Primary定义了一个默认值,而@Qualifier是非常特定的。
让我们看看使用@Primary注释的另一种方式,这次使用的是初始示例:
@Component@Primarypublic class FooFormatter implements Formatter { //...} @Componentpublic class BarFormatter implements Formatter { //...}
在本例中,@Primary注释被放在一个实现类中,将消除场景的歧义。
5. @Qualifier和 @Autowired按名称注入对比
在自动装配时选择多个bean的另一种方法是使用要注入的字段的名称。这是在没有其他Spring提示的情况下的默认值。让我们看一些基于我们最初的例子的代码:
public class FooService { @Autowired private Formatter fooFormatter;}
在本例中,Spring将确定要注入的bean是FooFormatter bean,因为字段名与我们在@Component注释中为该bean使用的值相匹配。
6. 总结
我们已经描述了需要消除要注入哪些bean的歧义的场景。特别是,我们描述了@Qualifier注释,并将其与其他确定需要使用哪些bean的类似方法进行了比较。