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

Spring Boot bean定义名称重复,如何不手动指定@Service名称解决

异常原因

org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'estatRegistreServiceImpl' for bean class [cat.gencat.catsalut.hes.mpi.api.loader.service.EstatRegistreServiceImpl] conflicts with existing, non-compatible bean definition of same name and class [cat.gencat.catsalut.hes.mpi.api.admin.service.impl.EstatRegistreServiceImpl]

该异常是Spring默认的注解Bean命名规则导致:默认将类名首字母小写作为Bean全局名称,你两个不同包下的EstatRegistreServiceImpl类名相同,因此生成的Bean名重复,触发全局唯一性校验失败。

最优解决方案:全局自定义Bean命名生成器(无需修改任何@Service注解)

自定义命名生成器,使用类的全限定名作为Bean名称,全限定名天然全局唯一,从根源避免重名冲突,完全不需要手动维护自定义Bean名字面量。

步骤1:实现自定义命名生成器

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;

public class FullQualifiedBeanNameGenerator extends AnnotationBeanNameGenerator {
    @Override
    protected String buildDefaultBeanName(BeanDefinition definition) {
        // 直接返回类的全限定名作为Bean名称
        return definition.getBeanClassName();
    }
}

步骤2:启用命名生成器

Spring Boot项目直接在启动类注解中指定:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication(nameGenerator = FullQualifiedBeanNameGenerator.class)
public class YourApplication {
    public static void main(String[] args) {
        SpringApplication.run(YourApplication.class, args);
    }
}

传统Spring XML配置项目修改组件扫描配置:

<context:component-scan 
    base-package="cat.gencat.catsalut.hes.mpi.api" 
    name-generator="你的包路径.FullQualifiedBeanNameGenerator"/>

说明

  • 完全不需要修改现有业务代码中的@Service、@Component等注解,新增业务类也不需要额外配置,一劳永逸。
  • 日常注入使用@Autowired按类型注入完全不受影响:两个EstatRegistreServiceImpl分别实现不同包下的EstatRegistreService接口,类型天然区分,不需要加@Qualifier。
  • 若确实需要按名称注入,填写对应类的全限定名即可:
    @Autowired
    @Qualifier("cat.gencat.catsalut.hes.mpi.api.admin.service.impl.EstatRegistreServiceImpl")
    private EstatRegistreService adminEstatRegistreService;
    

可选方案:按模块加前缀的命名生成器

如果觉得全限定名太长,可以自定义生成器根据包路径给不同模块的Bean加统一前缀,比如admin模块的Bean名加admin前缀,loader模块加loader前缀,生成的Bean名为adminEstatRegistreServiceImpl、loaderEstatRegistreServiceImpl,同样不会冲突:

@Override
protected String buildDefaultBeanName(BeanDefinition definition) {
    // 默认首字母小写的类名
    String defaultName = super.buildDefaultBeanName(definition);
    String fullClassName = definition.getBeanClassName();
    // 按包路径匹配加前缀
    if (fullClassName.contains("admin.service")) {
        return "admin" + defaultName.substring(0,1).toUpperCase() + defaultName.substring(1);
    } else if (fullClassName.contains("loader.service")) {
        return "loader" + defaultName.substring(0,1).toUpperCase() + defaultName.substring(1);
    }
    return defaultName;
}

配置方式和上述方案一致。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 21:48:04