詳解關(guān)于spring bean名稱命名的那些事
前言
用了多年spring,一直想當(dāng)然把spring默認(rèn)的beanName當(dāng)成是類名的首字母小寫,比如HelloService其beanName為helloService。直到有天對(duì)接了供方廠商的接口,他有個(gè)類形如ABService,于是用
getBean(“aBService”)
的方式獲取bean,結(jié)果取到是null,一開始以為是ABservice沒注入,后面采用
getBean(ABService.class)
能成功獲取到bean,說明ABService是有注入到IOC容器中,但是為啥用aBService獲取不到bean?于是就用如下代碼段,打印出相應(yīng)ABService對(duì)應(yīng)的beanName
applicationContext.getBeansOfType(ABService.class).forEach((beanName,bean)->{ System.out.println(beanName + ":" + bean); });
打印出來的結(jié)果,如下
ABService:com.github.lybgeek.ABService@245b6b85
beanName竟然是ABService,這就和之前的想當(dāng)然有出入。于是只好查看源碼
02源碼查看
源碼查看有2種方式,本文的示例是springboot項(xiàng)目
01從main方法直接調(diào)試斷點(diǎn)
從圖可以看出如果是以掃描注解注入形式,其beanName的生成規(guī)則是由
org.springframework.context.annotation.AnnotationBeanNameGenerator#generateBeanName
決定。
ps: 這種直接從main啟動(dòng)類調(diào)試起,比較適用于時(shí)間比較多,或者排查毫無頭緒
02帶著問題查看,靠猜加驗(yàn)證的方式
利用idea的find Usage查找引用,比如ABService的注解@service,我們可以直接查看哪個(gè)引用到@Service,再猜測(cè)下beanName的生成規(guī)則
通過猜,我們基本上就可以定位出比較符合我們需求的方法
03源碼驗(yàn)證
從上面的分析,我們可以知道如果是掃描bean注解注入的方式,其生成beanName規(guī)則,是在
org.springframework.context.annotation.AnnotationBeanNameGenerator
其生成規(guī)則代碼如下
@Override public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) { if (definition instanceof AnnotatedBeanDefinition) { String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition); if (StringUtils.hasText(beanName)) { // Explicit bean name found. return beanName; } } // Fallback: generate a unique default bean name. return buildDefaultBeanName(definition, registry); }
從代碼段,我們可以看出,注解上有取名,比如@Service(“abService”),則beanName為abService,如果沒有取名,則看
protected String buildDefaultBeanName(BeanDefinition definition) { String beanClassName = definition.getBeanClassName(); Assert.state(beanClassName != null, "No bean class name set"); String shortClassName = ClassUtils.getShortName(beanClassName); return Introspector.decapitalize(shortClassName); }
public static String decapitalize(String name) { if (name == null || name.length() == 0) { return name; } if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) && Character.isUpperCase(name.charAt(0))){ return name; } char chars[] = name.toCharArray(); chars[0] = Character.toLowerCase(chars[0]); return new String(chars); }
其實(shí)從代碼我們就很容易看出答案了,如果類名前兩個(gè)或以上個(gè)字母都是大寫,則beanName和類名就一樣了,不會(huì)進(jìn)行首字母小寫轉(zhuǎn)換。
decapitalize這個(gè)方法的注釋也寫得很清楚,注釋如下
/** * Utility method to take a string and convert it to normal Java variable * name capitalization. This normally means converting the first * character from upper case to lower case, but in the (unusual) special * case when there is more than one character and both the first and * second characters are upper case, we leave it alone. * <p> * Thus "FooBah" becomes "fooBah" and "X" becomes "x", but "URL" stays * as "URL". * * @param name The string to be decapitalized. * @return The decapitalized version of the string. */
04總結(jié)
通過掃描bean注解注入IOC時(shí),如果不指定bean名稱的默認(rèn)規(guī)則是類名的首字母小寫,如果類名前兩個(gè)或以上個(gè)字母都是大寫,那么bean名稱與類名一樣。
其實(shí)這個(gè)細(xì)節(jié)可能懂的都懂,本文的彩蛋主要是分享一下平時(shí)查看源碼的一點(diǎn)心得吧,哈哈
到此這篇關(guān)于spring bean名稱命名的文章就介紹到這了,更多相關(guān)spring bean名稱命名內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java實(shí)現(xiàn)給Word文件添加文字水印
Word中設(shè)置水印時(shí),可預(yù)設(shè)的文字或自定義文字設(shè)置為水印效果,但通常添加水印效果時(shí),會(huì)對(duì)所有頁面都設(shè)置成統(tǒng)一效果。本文將利用Java給Word每一頁設(shè)置不同文字水印效果,需要的可以參考一下2022-02-02dubbo擴(kuò)展點(diǎn)AOP切面功能擴(kuò)展示例詳解
這篇文章主要為大家介紹了dubbo擴(kuò)展點(diǎn)AOP切面功能擴(kuò)展示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08mybatis調(diào)用存儲(chǔ)過程的實(shí)例代碼
這篇文章主要介紹了mybatis調(diào)用存儲(chǔ)過程的實(shí)例,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-10-10SpringBoot+RabbitMQ?實(shí)現(xiàn)死信隊(duì)列的示例
本文主要介紹了SpringBoot+RabbitMQ?實(shí)現(xiàn)死信隊(duì)列的示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06Spring在多線程下@Resource注入為null的問題
這篇文章主要介紹了Spring在多線程下@Resource注入為null的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02java實(shí)現(xiàn)把兩個(gè)有序數(shù)組合并到一個(gè)數(shù)組的實(shí)例
今天小編就為大家分享一篇java實(shí)現(xiàn)把兩個(gè)有序數(shù)組合并到一個(gè)數(shù)組的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-05-05