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。由此,如果出現(xiàn)不同包結構下同樣的類名稱,肯定會出現(xiàn)沖突。
解決方案如下
1. 自己寫一個類實現(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. 在啟動類上加注解@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);?
? ? }?
}這樣,問題就可以解決了。
另外解決方式
解決辦法:
- 一:將其中一個實現(xiàn)類改為不同的名字;
- 二:將其中一個注解變更為一個name為非roleServiceImpl的注解@service(name="aaaa")。
別名:
@Autowired注解時,屬性名即為默認的Bean名,如下面的logPrint就是獲取beanName=logPrint的bean
@Resource(name=xxx) 直接指定Bean的name,來唯一選擇匹配的bean
說明:
@Primary注解
這個注解就是為了解決當有多個bean滿足注入條件時,有這個注解的實例被選中
- @Resource 指定beanName的是否會被@Primary影響
- 前面的@Autowired注解 + 屬性名的方式,是按照第一節(jié)的方式選擇呢,還是選擇被@Primary標識的實例
- @Autowired + 隨意的一個非beanName的屬性,驗證是否會選中@Primary標識的注解
- 根據(jù)前面的執(zhí)行,因此可以知曉,選擇bean的方式如下
存在@Primary注解時
- @Resource注解指定name時,根據(jù)name來查找對應的bean
- @Autowired注解,全部都用@Primary標識的注解
- @Primary注解要求唯一(非廣義的唯一性,并不是指只能用一個@Primary,具體看前面)
不存在@Primary注解時
- @Resource注解指定name時,根據(jù)name來查找對應的bean
- @Autowired注解時,根據(jù)屬性名去查對應的Bean,如果查不到則拋異常;如果查到,那即是它了
總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
java中實現(xiàn)map與對象相互轉換的幾種實現(xiàn)
這篇文章主要介紹了java中實現(xiàn)map與對象相互轉換的幾種實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-07-07
java使用Socket類接收和發(fā)送數(shù)據(jù)
Socket類是負責處理客戶端通信的Java類。本文主要是介紹java使用Socket類接收和發(fā)送數(shù)據(jù),具有一定的參考價值,感興趣的小伙伴們可以參考一下。2016-10-10
Java如何實現(xiàn)http接口參數(shù)和返回值加密
這篇文章主要介紹了Java如何實現(xiàn)http接口參數(shù)和返回值加密問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-11-11
詳解Springboot @Cacheable 注解(指定緩存位置)
這篇文章主要介紹了詳解Springboot @Cacheable 注解(指定緩存位置),使用? @Cacheable ?注解就可以將運行結果緩存,以后查詢相同的數(shù)據(jù),直接從緩存中取,不需要調用方法,需要的朋友可以參考下2023-09-09
Java解決Collectors.toMap()空指針報錯問題的方法詳解
這篇文章主要為大家詳細介紹了Java解決Collectors.toMap()空指針報錯問題的相關方法,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下2026-03-03
java中int轉string與string轉int的效率對比
這篇文章主要介紹了java中int轉string與string轉int的效率對比,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03

