Spring 注解 @Qualifier 详细解析

张开发
2026/4/5 17:47:36 15 分钟阅读

分享文章

Spring 注解 @Qualifier 详细解析
1. 概述今天带你了解一下Spring框架中的Qualifier注解它解决了哪些问题以及如何使用它。我们还将了解它与Primary注解的不同之处。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注解就是其中之一。跟着小胖哥的节奏往下走。3. Qualifier通过使用Qualifier注解我们可以消除需要注入哪个bean的问题。让我们重新回顾一下前面的例子看看我们如何通过包含Qualifier注释来指出我们想要使用哪个bean来解决问题Component public class FooService { Autowired Qualifier(fooFormatter) private Formatter formatter; //todo }通过将Qualifier注解与我们想要使用的特定Spring bean的名称一起进行装配Spring框架就能从多个相同类型并满足装配要求的bean中找到我们想要的避免让Spring脑裂。我们需要做的是Component或者Bean注解中声明的value属性以确定名称。其实我们也可以在Formatter实现类上使用Qualifier注释而不是在Component或者Bean中指定名称也能达到相同的效果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。我们来看一个例子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的示例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将确定要注入的bean是FooFormatter因为字段名称与我们在该bean的Component或者Bean注解中使用的值(默认Bean使用方法名)相匹配。6. 总结通过对Qualifier的探讨我们知道该注解是用来消除依赖注入冲突的。这种在日常开发比如Rabbtimq的队列声明中很常见。小胖哥也通过该注解和其他上述注解的组合使用和对比中展示了一些常用的用法。这将有助于你对Spring的依赖注入机制的了解。

更多文章