Spring 注解 @Qualifier 详细解析

1. 概述

今天带你了解一下 Spring 框架中的 @Qualifier 注解,它解决了哪些问题,以及如何使用它。咱们还将了解它与 @Primary 注解的不一样之处。更多的技术解析请访问 felord.cnjava

2. 痛点

使用 @Autowired 注解是 Spring 依赖注入的绝好方法。可是有些场景下仅仅靠这个注解不足以让Spring知道到底要注入哪一个 bean。 默认状况下,@Autowired 按类型装配 Spring Bean。 若是容器中有多个相同类型的 bean,则框架将抛出 NoUniqueBeanDefinitionException, 以提示有多个知足条件的 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;
        
        //todo 
    }
复制代码

若是咱们尝试将 FooService 加载到咱们的上下文中,Spring 框架将抛出 NoUniqueBeanDefinitionException。这是由于 Spring 不知道要注入哪一个 bean。为了不这个问题,有几种解决方案。那么咱们本文要讲解的 @Qualifier 注解就是其中之一。跟着小胖哥的节奏往下走。spa

3. @Qualifier

经过使用 @Qualifier 注解,咱们能够消除须要注入哪一个 bean 的问题。让咱们从新回顾一下前面的例子,看看咱们如何经过包含 @Qualifier 注释来指出咱们想要使用哪一个 bean 来解决问题:code

@Component
    public class FooService {
        @Autowired
        @Qualifier("fooFormatter")
        private Formatter formatter;
        
        //todo 
    }
复制代码

经过将 @Qualifier 注解与咱们想要使用的特定 Spring bean 的名称一块儿进行装配,Spring 框架就能从多个相同类型并知足装配要求的 bean 中找到咱们想要的,避免让Spring脑裂。咱们须要作的是@Component或者@Bean注解中声明的value属性以肯定名称。 其实咱们也能够在 Formatter 实现类上使用 @Qualifier 注释,而不是在 @Component 或者 @Bean 中指定名称,也能达到相同的效果:orm

@Component
     @Qualifier("fooFormatter")
     public class FooFormatter implements Formatter {
         public String format() {
             return "foo";
         }
     }
 
     @Component
     @Qualifier("barFormatter")
     public class BarFormatter implements Formatter {
         public String format() {
             return "bar";
         }
     }
复制代码

4. @Qualifier VS @Primary

还有另外一个名为 @Primary 的注解,咱们也能够用来发生依赖注入的歧义时决定要注入哪一个 bean。当存在多个相同类型的 bean 时,此注解定义了首选项。除非另有说明,不然将使用与 @Primary 注释关联的 bean 。 咱们来看一个例子:cdn

@Bean
    public Employee tomEmployee() {
        return new Employee("Tom");
    }

    @Bean
    @Primary
    public Employee johnEmployee() {
        return new Employee("john");
    }
复制代码

在此示例中,两个方法都返回相同的 Employee类型。Spring 将注入的 bean 是方法 johnEmployee 返回的 bean。这是由于它包含 @Primary 注解。当咱们想要指定默认状况下应该注入特定类型的 bean 时,此注解颇有用。 若是咱们在某个注入点须要另外一个 bean,咱们须要专门指出它。咱们能够经过 @Qualifier 注解来作到这一点。例如,咱们能够经过使用 @Qualifier 注释来指定咱们想要使用 tomEmployee 方法返回的 bean 。 值得注意的是,若是 @Qualifier@Primary 注释都存在,那么 @Qualifier 注释将具备优先权。基本上,@Primary 是定义了默认值,而 @Qualifier 则很是具体。 固然@Component 也可使用@Primary 注解,此次使用的仍是上面3的示例:blog

@Component
     @Primary
     public class FooFormatter implements Formatter {
         public String format() {
             return "foo";
         }
     }
 
     @Component
     public class BarFormatter implements Formatter {
         public String format() {
             return "bar";
         }
     }
复制代码

在这种状况下,@Primary 注解指定了默认注入的是 FooFormatter,消除了场景中的注入歧义。队列

5. 经过名称来自动注入

在使用 @Autowired 进行自动装配时,若是 Spring 没有其余提示,将会按照须要注入的变量名称来寻找合适的 bean。也能够解决依赖注入歧义的问题。让咱们看一些基于咱们最初的例子的代码:开发

@Component
    public class FooService {
        @Autowired
        private Formatter fooFormatter;
        
        //todo 
    }
复制代码

在这种状况下,Spring 将肯定要注入的 beanFooFormatter,由于字段名称与咱们在该 bean@Component或者 @Bean 注解中使用的值(默认 @Bean 使用方法名)相匹配。get

6. 总结

经过对 @Qualifier 的探讨,咱们知道该注解是用来消除依赖注入冲突的。这种在平常开发,好比 Rabbtimq 的队列声明中很常见。小胖哥也经过该注解和其余上述注解的组合使用和对比中展现了一些经常使用的用法。这将有助于你对 Spring 的依赖注入机制的了解。

关注公众号:Felordcn获取更多资讯

我的博客:https://felord.cn

相关文章
相关标签/搜索