Java 实用注解篇之@Qualifier 深度解析及实战案例

 更新时间:2025年06月06日 10:37:40   作者:Stay Passion  
在Spring框架中,@Qualifier是一个常见的注解,主要用于解决依赖注入(DI)时的歧义性,本文给大家介绍Java 实用注解篇之@Qualifier 深度解析及实战案例,感兴趣的朋友一起看看吧

前言

        在 Spring 框架中,@Qualifier 是一个常见的注解,主要用于 解决依赖注入(DI)时的歧义性。当一个接口有多个实现类时,Spring 无法自动决定该注入哪个具体的 Bean,此时 @Qualifier 可以帮助我们 指定要注入的 Bean 名称

一、@Qualifier 的作用

1️⃣ 解决 Spring 依赖注入冲突

当有多个 Bean 可用于注入时,Spring 需要知道应该选择哪一个:

  • 如果没有 @Qualifier,Spring 会抛出 NoUniqueBeanDefinitionException
  • 使用 @Qualifier,可以明确指定要注入的 Bean。

2️⃣ @Qualifier 基本使用

示例:多个相同类型的 Bean 时,Spring 无法自动选择

@Component
public class Dog implements Animal {
    @Override
    public void speak() {
        System.out.println("汪汪!");
    }
}
@Component
public class Cat implements Animal {
    @Override
    public void speak() {
        System.out.println("喵喵!");
    }
}
@Service
public class AnimalService {
    private final Animal animal;
    @Autowired
    public AnimalService(Animal animal) {
        this.animal = animal;
    }
    public void makeSound() {
        animal.speak();
    }
}

此时运行时会报错:

NoUniqueBeanDefinitionException: No qualifying bean of type 'Animal' available

因为 DogCat 都实现了 Animal,Spring 不知道该注入哪个。

✅ 解决方案:使用 @Qualifier 指定具体 Bean

@Service
public class AnimalService {
    private final Animal animal;
    @Autowired
    public AnimalService(@Qualifier("dog") Animal animal) {
        this.animal = animal;
    }
    public void makeSound() {
        animal.speak();
    }
}

这样 AnimalService 只会注入 dog 这个 Bean,避免了冲突。

二、@Qualifier 源码解析

1️⃣ @Qualifier 注解的定义

Spring 框架中的 @Qualifier 是一个 标准注解,定义如下:

@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Qualifier {
    String value();
}

可以看到:

  • @Target 允许它用于 字段、参数、方法和类
  • @Retention(RetentionPolicy.RUNTIME) 让它在 运行时生效
  • String value() 方法表示指定的 Bean 名称。

2️⃣ Spring 解析 @Qualifier

Spring 在 AutowiredAnnotationBeanPostProcessor 中解析 @Qualifier

if (methodParameter.hasParameterAnnotation(Qualifier.class)) {
    String beanName = methodParameter.getParameterAnnotation(Qualifier.class).value();
    bean = beanFactory.getBean(beanName, methodParameter.getParameterType());
}

解析过程:

  • 检查 @Qualifier 是否存在,如果存在就获取 value()
  • 根据 value() 找到 Bean 并进行注入。

三、@Qualifier 实战案例

1️⃣ @Qualifier 结合 @Autowired

如果有多个 Bean,使用 @Qualifier 指定注入的 Bean:

@Component("catBean")
public class Cat implements Animal {
    @Override
    public void speak() {
        System.out.println("喵喵!");
    }
}
@Component("dogBean")
public class Dog implements Animal {
    @Override
    public void speak() {
        System.out.println("汪汪!");
    }
}
@Service
public class AnimalService {
    @Autowired
    @Qualifier("dogBean")
    private Animal animal;
    public void makeSound() {
        animal.speak();
    }
}

AnimalService 只会注入 dogBean,避免 NoUniqueBeanDefinitionException

2️⃣ @Qualifier 结合 @Bean

如果 Bean 是通过 @Bean 方法创建的,也可以使用 @Qualifier 指定:

@Configuration
public class AnimalConfig {
    @Bean
    @Qualifier("bigDog")
    public Animal bigDog() {
        return new Dog();
    }
    @Bean
    @Qualifier("smallDog")
    public Animal smallDog() {
        return new Dog();
    }
}
@Service
public class AnimalService {
    @Autowired
    @Qualifier("bigDog")
    private Animal animal;
}

✅ 这样可以选择 bigDog 而不是 smallDog

3️⃣ @Qualifier 结合 @Primary

如果希望默认注入某个 Bean,但仍然允许 @Qualifier 选择其他 Bean,可以结合 @Primary

@Component
@Primary
public class DefaultAnimal implements Animal {
    @Override
    public void speak() {
        System.out.println("我是默认动物!");
    }
}
@Service
public class AnimalService {
    @Autowired
    private Animal animal;  // 默认注入 DefaultAnimal
    @Autowired
    @Qualifier("dog")
    private Animal dog;  // 指定注入 Dog
}

animal 默认注入 DefaultAnimaldog 注入 Dog,两者互不干扰。

四、@Qualifier 使用注意事项

✅ 1. @Qualifier 不能用于构造方法

错误示例

@Service
public class AnimalService {
    private final Animal animal;
    @Autowired
    public AnimalService(@Qualifier("dog") Animal animal) {  // ❌ 无效
        this.animal = animal;
    }
}

正确方式

@Service
public class AnimalService {
    private final Animal animal;
    @Autowired
    public AnimalService(@Qualifier("dogBean") Animal animal) {  // ✅ 正确
        this.animal = animal;
    }
}

✅ 2. @Qualifier 不能和 @Primary 冲突

@Component
@Primary
@Qualifier("dog")
public class Dog implements Animal { }  // ❌ 不要同时使用 @Primary 和 @Qualifier

@Primary@Qualifier 逻辑上是冲突的,应该 只使用一个 来指定注入。

✅ 3. @Qualifier 必须匹配 Bean 名称

如果 @Qualifier("dogBean"),但 Bean 名称是 "dog",会导致找不到 Bean:

@Autowired
@Qualifier("dogBean")  // ❌ 错误
private Animal animal;

Spring 需要 @Qualifier("dog") 才能正确注入。

五、总结

重点说明
@Qualifier解决多个 Bean 注入冲突,指定具体 Bean
@Qualifier + @Autowired选择特定 Bean 进行注入
@Qualifier + @Bean@Configuration 中手动指定 Bean
@Primary + @Qualifier默认注入 @Primary,但可以用 @Qualifier 覆盖
注意事项@Qualifier 必须匹配 Bean 名称,避免和 @Primary 冲突

六、思考与拓展

  • @Qualifier 能否和 @Lazy 结合使用?
  • @Qualifier 在 Spring Boot @Conditional 配置中的应用?
  • @Qualifier 结合 Spring AOP 是否有特殊用法?

到此这篇关于Java 实用注解篇之@Qualifier 深度解析及实战案例的文章就介绍到这了,更多相关Java 注解@Qualifier 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JavaWeb实现简单上传文件功能

    JavaWeb实现简单上传文件功能

    这篇文章主要为大家详细介绍了JavaWeb实现简单上传文件功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • 详解mybatis-plus使用@EnumValue注解的方式对枚举类型的处理

    详解mybatis-plus使用@EnumValue注解的方式对枚举类型的处理

    这篇文章主要介绍了详解mybatis-plus使用@EnumValue注解的方式对枚举类型的处理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • mybatis xml注释sql的注意事项及说明

    mybatis xml注释sql的注意事项及说明

    这篇文章主要介绍了mybatis xml注释sql的注意事项及说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • 详解Spring如何解析占位符

    详解Spring如何解析占位符

    Spring一直支持将属性定义到外部的属性的文件中,并使用占占位符的形式为使用"${}"包装的属性名称,为了使用属性占位符,我们必须配置一个PropertyPlaceholderConfigurer或PropertySourcesPlaceholderConfigurer实例,本文将介绍如何解析占位符
    2021-06-06
  • SpringBoot+ShardingSphereJDBC实现读写分离详情

    SpringBoot+ShardingSphereJDBC实现读写分离详情

    这篇文章主要介绍了SpringBoot+ShardingSphereJDBC实现读写分离详情,通过用​​MySQL​​进行一主一从的主从复制展开全文内容,需要的朋友可以参考一下
    2022-08-08
  • Maven配置多仓库无效的解决

    Maven配置多仓库无效的解决

    在项目中使用Maven管理jar包依赖往往会出现很多问题,所以这时候就需要配置Maven多仓库,本文介绍了如何配置以及问题的解决
    2021-05-05
  • EL表达式简介_动力节点Java学院整理

    EL表达式简介_动力节点Java学院整理

    EL全名为Expression Language,这篇文章主要给大家介绍EL表达式的主要作用及内容简介,感兴趣的朋友一起看看
    2017-07-07
  • 用Java实现全国天气预报的api接口调用示例

    用Java实现全国天气预报的api接口调用示例

    查询天气预报在APP中常用的一个常用功能,本文实例讲述了java调用中国天气网api获得天气预报信息的方法。分享给大家供大家参考。
    2016-10-10
  • 5分钟快速学会spring boot整合Mybatis的方法

    5分钟快速学会spring boot整合Mybatis的方法

    这篇文章主要给大家介绍了如何通过5分钟快速学会spring boot整合Mybatis的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用spring boot具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-12-12
  • Java中如何判断是否为闰年详细实例

    Java中如何判断是否为闰年详细实例

    所谓闰年就是指2月有29天的那一年,下面这篇文章主要给大家介绍了关于Java中如何判断是否为闰年的相关资料,文中通过图文以及实例代码介绍的非常详细,需要的朋友可以参考下
    2023-06-06

最新评论