SpringBoot解決同名類導(dǎo)致的bean名沖突bean name conflicts問(wèn)題
SpringBoot同名類導(dǎo)致的bean名沖突bean name conflicts
問(wèn)題描述
項(xiàng)目中有兩個(gè)同名類都叫MyService,只是放在不同的包名下
package com.yeyuanxinyi; @Service() public class MyService { }
package com.yeyuanxiner; @Service() public class MyService { }
當(dāng)項(xiàng)目啟動(dòng)的時(shí)候會(huì)報(bào)如下錯(cuò)誤
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
解決方法
問(wèn)題分析:
由于以上兩個(gè)同名類在用@Service注解的時(shí)候未指定value值,所以Spring Boot默認(rèn)會(huì)以類名作為bean name,由于兩個(gè)類名相同導(dǎo)致了bean name相同的沖突
可以通過(guò)為同名類指定不同的bean name來(lái)解決問(wèn)題,上面兩個(gè)同名類修改后如下
再次運(yùn)行項(xiàng)目就不會(huì)報(bào)錯(cuò)了
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不同包結(jié)構(gòu)下,同名類沖突導(dǎo)致服務(wù)啟動(dòng)失敗解決方案
項(xiàng)目背景:
兩個(gè)項(xiàng)目的包結(jié)構(gòu)和類名都很多相同,于是開始考慮使用加一級(jí)包進(jìn)行隔離,類似于這種結(jié)構(gòu)
但是在啟動(dòng)的過(guò)程中,拋出來(lái)這樣的異常:
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默認(rèn)使用的是AnnotationBeanNameGenerator,它生成beanName的策略就是,取當(dāng)前類名(不是全限定類名)作為beanName。由此,如果出現(xiàn)不同包結(jié)構(gòu)下同樣的類名稱,肯定會(huì)出現(xiàn)沖突。
解決方案如下
1. 自己寫一個(gè)類實(shí)現(xiàn) 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. 在啟動(dòng)類上加注解@ComponentScan(nameGenerator = UniqueNameGenerator.class)使剛才我們自定義的BeanName生成策略生效?!?/p>
@SpringBootApplication? @ComponentScan(nameGenerator = UniqueNameGenerator.class) public class BeanNameConflictApplication {?? ? ? public static void main(String[] args) {? ? ? ? ? SpringApplication.run(BeanNameConflictApplication.class, args);? ? ? }? }
這樣,問(wèn)題就可以解決了。
另外解決方式
解決辦法:
- 一:將其中一個(gè)實(shí)現(xiàn)類改為不同的名字;
- 二:將其中一個(gè)注解變更為一個(gè)name為非roleServiceImpl的注解@service(name="aaaa")。
別名:
@Autowired注解時(shí),屬性名即為默認(rèn)的Bean名,如下面的logPrint就是獲取beanName=logPrint的bean
@Resource(name=xxx) 直接指定Bean的name,來(lái)唯一選擇匹配的bean
說(shuō)明:
@Primary注解
這個(gè)注解就是為了解決當(dāng)有多個(gè)bean滿足注入條件時(shí),有這個(gè)注解的實(shí)例被選中
- @Resource 指定beanName的是否會(huì)被@Primary影響
- 前面的@Autowired注解 + 屬性名的方式,是按照第一節(jié)的方式選擇呢,還是選擇被@Primary標(biāo)識(shí)的實(shí)例
- @Autowired + 隨意的一個(gè)非beanName的屬性,驗(yàn)證是否會(huì)選中@Primary標(biāo)識(shí)的注解
- 根據(jù)前面的執(zhí)行,因此可以知曉,選擇bean的方式如下
存在@Primary注解時(shí)
- @Resource注解指定name時(shí),根據(jù)name來(lái)查找對(duì)應(yīng)的bean
- @Autowired注解,全部都用@Primary標(biāo)識(shí)的注解
- @Primary注解要求唯一(非廣義的唯一性,并不是指只能用一個(gè)@Primary,具體看前面)
不存在@Primary注解時(shí)
- @Resource注解指定name時(shí),根據(jù)name來(lái)查找對(duì)應(yīng)的bean
- @Autowired注解時(shí),根據(jù)屬性名去查對(duì)應(yīng)的Bean,如果查不到則拋異常;如果查到,那即是它了
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Mybatis返回int或者Integer類型報(bào)錯(cuò)的解決辦法
這篇文章主要介紹了Mybatis返回int或者Integer類型報(bào)錯(cuò)的解決辦法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-12-12關(guān)于Java中修飾符的總結(jié)(fina除外)
下面小編就為大家?guī)?lái)一篇關(guān)于Java中修飾符的總結(jié)(fina除外)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-09-09Spring cloud Gateway簡(jiǎn)介及相關(guān)配置方法
這篇文章主要介紹了Spring cloud Gateway簡(jiǎn)介及相關(guān)配置方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-04-04Springboot?異步任務(wù)和定時(shí)任務(wù)的異步處理
本文介紹了Springboot異步任務(wù)和定時(shí)任務(wù)的異步處理,Springboot?中,異步任務(wù)和定時(shí)任務(wù)是經(jīng)常遇到的處理問(wèn)題方式,為了能夠用好這兩項(xiàng)配置,不干擾正常的業(yè)務(wù),需要對(duì)其進(jìn)行異步化配置。怎么設(shè)置合理的異步處理線程就是其核心和關(guān)鍵,下文詳情需要的朋友可以參考下2022-05-05RxJava2.x+ReTrofit2.x多線程下載文件的示例代碼
本篇文章主要介紹了RxJava2.x+ReTrofit2.x多線程下載文件的示例代碼,具有一定的參考價(jià)值,有興趣的可以了解一下2017-09-09Kafka日志清理實(shí)現(xiàn)詳細(xì)過(guò)程講解
這篇文章主要為大家介紹了Kafka日志清理實(shí)現(xiàn)詳細(xì)過(guò)程講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05