bigywater.tech
Spring · 177

NoUniqueBeanDefinitionException:两个候选 Bean 时,字段名、@Primary、@Qualifier、-parameters 各管什么

NoUniqueBeanDefinitionException 怎么修?字段名、@Primary、@Qualifier 各起什么作用,两个 @Primary 会怎样,@Qualifier 拼错报什么,ObjectProvider 的几个方法有什么差别?这篇用同一对 Bean 在 Spring Boot 4.0.8 上逐个试。

字段名也能选
多个候选且没有注解时,字段名与 Bean 名相同就能注入成功;构造器参数名要靠 -parameters 才行
getIfUnique 返回 null
两个候选时 ObjectProvider.getIfUnique() 不抛异常,返回 null
两个 @Primary
仍然抛 NoUniqueBeanDefinitionException,信息是 more than one 'primary' bean found,没有整齐的 FailureAnalyzer 报告

报错

实测 · 本机执行输出
  启动失败:NoUniqueBeanDefinitionException
    报告:Field g in demo.c1.Consumer required a single bean, but 2 were found:
    报告:- englishGreeter: defined by method 'englishGreeter' in demo.c1.Cfg
    报告:- chineseGreeter: defined by method 'chineseGreeter' in demo.c1.Cfg
    报告:This may be due to missing parameter name information
    报告:Action:
    报告:Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
    报告:Ensure that your compiler is configured to use the '-parameters' flag.
    报告:You may need to update both your build tool settings as well as your IDE.
    报告:(See https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-6.1-Release-Notes#parameter-name-retention)
    报告:RES   启动失败:NoUniqueBeanDefinitionException

字段名 g、两个候选,启动失败。

字段名

实测 · 本机执行输出
  注入成功:hello
  启动成功

字段名与 Bean 名相同就注入成功。

@Primary

实测 · 本机执行输出
  注入成功:你好
  启动成功

标在 chineseGreeter 上。

@Qualifier

实测 · 本机执行输出
  注入成功:你好
  启动成功

值是 Bean 名。

两个 @Primary

实测 · 本机执行输出
  启动失败:NoUniqueBeanDefinitionException
    没有 FailureAnalyzer 报告,日志里是完整堆栈;最后一个 Caused by:org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'demo.c5.Greeter' available: more than one 'primary' bean found among candidates: [englishGreeter, chineseGreeter]

more than one primary。

@Qualifier 拼错

实测 · 本机执行输出
  启动失败:NoSuchBeanDefinitionException
    报告:Field g in demo.c6.Consumer required a bean of type 'demo.c6.Greeter' that could not be found.
    报告:The injection point has the following annotations:
    报告:- @org.springframework.beans.factory.annotation.Autowired(required=true)
    报告:- @org.springframework.beans.factory.annotation.Qualifier("chinseGreeter")
    报告:The following candidates were found but could not be injected:
    报告:- User-defined bean method 'englishGreeter' in 'Cfg'
    报告:- User-defined bean method 'chineseGreeter' in 'Cfg'
    报告:Action:
    报告:Consider revisiting the entries above or defining a bean of type 'demo.c6.Greeter' in your configuration.
    报告:RES   启动失败:NoSuchBeanDefinitionException

报 NoSuchBeanDefinitionException。

List 与 Map

实测 · 本机执行输出
  List 里依次是:[你好, hello];Map 的键:[englishGreeter, chineseGreeter]
  启动成功

不会触发异常,List 按 @Order。

ObjectProvider

实测 · 本机执行输出
  getIfUnique() = null
  stream().count() = 2
  getIfAvailable() 抛 NoUniqueBeanDefinitionException
  getObject() 抛 NoUniqueBeanDefinitionException
  启动成功

getIfUnique 静默返回 null。

构造器参数名

实测 · 本机执行输出
  注入成功:hello
  启动成功

带 -parameters 能对上。

不带 -parameters

实测 · 本机执行输出
  class 文件里是否带 MethodParameters 属性:否(对照:加 -parameters 编译的那份:是)
  启动失败:NoUniqueBeanDefinitionException
    报告:Parameter 0 of constructor in demo.c9.Consumer required a single bean, but 2 were found:
    报告:- englishGreeter: defined by method 'englishGreeter' in demo.c9.Cfg
    报告:- chineseGreeter: defined by method 'chineseGreeter' in demo.c9.Cfg
    报告:This may be due to missing parameter name information
    报告:Action:
    报告:Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
    报告:Ensure that your compiler is configured to use the '-parameters' flag.
    报告:You may need to update both your build tool settings as well as your IDE.
    报告:(See https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-6.1-Release-Notes#parameter-name-retention)
    报告:RES   启动失败:NoUniqueBeanDefinitionException

对不上,启动失败。

分步演示

NoUnique
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK 21.0.12(Homebrew) / Spring Boot 4.0.8(Spring Framework 7.0.9、Tomcat 11.0.24) / Spring Cloud 2025.1.3;用 javac 编译、java 直接运行,依赖由 Maven 从 Maven Central 解析;数字每次运行会有小幅抖动(Spring Boot 4.0.8 的 spring-boot 与 spring-boot-autoconfigure,不带 Web;每个情形是一个包里的 Greeter 接口、@Bean 方法和 @Component 消费者,用 SpringApplication 启动;FailureAnalyzer 的报告通过 logback ERROR 级别打印;「不带 -parameters」的编译是单独调用 javac 完成,并用 javap 确认 class 文件里没有 MethodParameters)
    • 没有验证:Gradle 或 Maven 插件默认是否带 -parameters;Kotlin 项目;@Resource(按名字注入)的行为;@Priority 与 @Order 的差别;泛型类型作为区分条件(Repository 与 Repository);@Qualifier 自定义注解;@Lazy 注入;Map 的键顺序为什么是注册顺序(只记录了现象)
    京ICP备2026067502号-1京公网安备11010502063487号