Contents

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*注释中使用的值匹配。