java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringBoot同名类导致bean名冲突bean name conflicts

SpringBoot解决同名类导致的bean名冲突bean name conflicts问题

作者:野猿新一

这篇文章主要介绍了SpringBoot解决同名类导致的bean名冲突bean name conflicts问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

SpringBoot同名类导致的bean名冲突bean name conflicts

问题描述

项目中有两个同名类都叫MyService,只是放在不同的包名下

package com.yeyuanxinyi;
@Service()
public class MyService {
}
package com.yeyuanxiner;
@Service()
public class MyService {
}

当项目启动的时候会报如下错误

Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'MyService' for bean class [com.yeyuanxinyi.MyService] conflicts with existing, non-compatible bean definition of same name and class [com.yeyuanxiner.MyService]
    at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.checkCandidate(ClassPathBeanDefinitionScanner.java:348)
    at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:286)
    at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:132)
    at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:287)
    at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:242)
    at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:199)
    at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:167)
    ... 13 common frames omitted

解决方法

问题分析:

由于以上两个同名类在用@Service注解的时候未指定value值,所以Spring Boot默认会以类名作为bean name,由于两个类名相同导致了bean name相同的冲突

可以通过为同名类指定不同的bean name来解决问题,上面两个同名类修改后如下

再次运行项目就不会报错了

package com.yeyuanxinyi;
@Service("MyService1")
public class MyService {
}
package com.yeyuanxiner;
@Service("MyService2")
public class MyService {
}

同理,以上解决方法也适用于@Component

package com.yeyuanxiner;
@Component("MyComponent1")
public class MyComponent {
}

SpringBoot不同包结构下,同名类冲突导致服务启动失败解决方案

项目背景:

两个项目的包结构和类名都很多相同,于是开始考虑使用加一级包进行隔离,类似于这种结构

但是在启动的过程中,抛出来这样的异常:

Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'nameConflict' for bean class [xom.liuyun.beannameconflict.modelB.NameConflict] conflicts with existing, non-compatible bean definition of same name and class [xom.liuyun.beannameconflict.modelA.NameConflict]

at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.checkCandidate(ClassPathBeanDefinitionScanner.java:348) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]

at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:286) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]

at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:132) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]

at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:284) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]

at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:241) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]

at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:198) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]

at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:166) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]

... 13 common frames omitted。

原因:

spring提供两种beanName生成策略,基于注解的sprong-boot默认使用的是AnnotationBeanNameGenerator,它生成beanName的策略就是,取当前类名(不是全限定类名)作为beanName。由此,如果出现不同包结构下同样的类名称,肯定会出现冲突。

解决方案如下

1. 自己写一个类实现 org.springframework.beans.factory.support.BeanNameGeneraot接口

public class UniqueNameGenerator extends AnnotationBeanNameGenerator {
     @Override
    public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
        //全限定类名
        String beanName = definition.getBeanClassName();
        return beanName;
    }
}

2. 在启动类上加注解@ComponentScan(nameGenerator = UniqueNameGenerator.class)使刚才我们自定义的BeanName生成策略生效。 

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

这样,问题就可以解决了。

另外解决方式

解决办法:

别名:

@Autowired注解时,属性名即为默认的Bean名,如下面的logPrint就是获取beanName=logPrint的bean

@Resource(name=xxx) 直接指定Bean的name,来唯一选择匹配的bean

说明:

@Primary注解

这个注解就是为了解决当有多个bean满足注入条件时,有这个注解的实例被选中

存在@Primary注解时

不存在@Primary注解时

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文