Spring @qualifier注解
1.概述
在本教程中,我们将探讨*@Qualifier*注解可以帮助我们解决哪些问题,以及如何使用它。
2. Autowire 需要消歧义
@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";
}
}
@Component
public class FooService {
@Autowired
private Formatter formatter;
}
如果我们尝试将FooService加载到我们的上下文中,Spring 框架将抛出NoUniqueBeanDefinitionException。这是因为Spring 不知道要注入哪个 bean。为了避免这个问题,有几种解决方案;@Qualifier注释就是其中之一。
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 。
让我们看一个例子:
@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定义了一个默认值,而@Qualifier*非常具体。
让我们看一下使用*@Primary*注解的另一种方式,这次使用初始示例:
@Component
@Primary
public class FooFormatter implements Formatter {
//...
}
@Component
public class BarFormatter implements Formatter {
//...
}
**在这种情况下,@Primary注释被放置在实现类之一中,**并将消除场景的歧义。
5. @Qualifier与按名称自动装配
自动装配时在多个 bean 之间做出决定的另一种方法是使用要注入的字段的名称。这是默认设置,以防 Spring 没有其他提示。让我们看一些基于我们最初示例的代码:
public class FooService {
@Autowired
private Formatter fooFormatter;
}
在这种情况下,Spring 将确定要注入的 bean 是FooFormatter的,因为字段名称与我们在该 bean 的*@Component*注释中使用的值匹配。