You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用FullyQualifiedAnnotationBeanNameGenerator启动SpringBoot时抛出NoUniqueBeanDefinitionException问题排查

这是个挺有意思的问题,我来拆解一下背后的原因和解决方案:

为什么MyRepository接口会被注册为bean?

你没给MyRepository加@Component或相关注解,它却被注册成bean,核心原因出在FullyQualifiedAnnotationBeanNameGenerator和MyBatis-Spring的交互上。

MyBatis的@MapperScan本来只会扫描带@Mapper注解的接口(也就是你的MyRepositoryImpl),并为它生成代理bean。但当你指定FullyQualifiedAnnotationBeanNameGenerator作为名称生成器时,MyBatis-Spring的扫描逻辑出现了特殊行为:它会把MyRepositoryImpl的父接口MyRepository也错误地注册为一个bean——哪怕MyRepository没有@Mapper注解。

这就导致Spring容器里出现了两个类型为MyRepository的bean:一个是MyRepositoryImpl的代理实例,另一个是莫名其妙被注册的MyRepository接口对应的bean,最终触发NoUniqueBeanDefinitionException。

为什么不用这个NameGenerator就正常?

默认的AnnotationBeanNameGenerator是用类的短名称(比如myRepositoryImpl)作为bean名称的。搭配MyBatis-Spring时,它不会触发上述的父接口错误注册逻辑——只会为带@Mapper的MyRepositoryImpl生成一个代理bean。此时容器里只有一个符合MyRepository类型的bean,依赖注入自然没问题。

解决方案

  1. 显式限定@MapperScan的扫描规则:如果必须用FullyQualifiedAnnotationBeanNameGenerator,可以在@MapperScan里明确指定只扫描带@Mapper注解的接口,避免父接口被误注册:
    @MapperScan(
        nameGenerator = FullyQualifiedAnnotationBeanNameGenerator.class,
        annotationClass = Mapper.class // 显式指定只扫描带@Mapper的接口
    )
    
  2. 调整依赖注入的类型:如果可以接受,在MyService里直接注入MyRepositoryImpl而不是MyRepository,但这违背了面向接口编程的原则,不推荐。
  3. 使用默认名称生成器:如果没有特殊需求,直接去掉nameGenerator配置,用默认的AnnotationBeanNameGenerator是最稳妥的选择。

内容的提问来源于stack exchange,提问作者avenue68

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 09:42:28