透過Spring源碼查看Bean的命名轉(zhuǎn)換規(guī)則圖文詳解
前言
近期在寫Spring項(xiàng)目的時(shí)候,需要通過注解的形式去替代之前直接將Bean存放在Spring容器這種方式,以此來簡化對于Bean對象的操作,但是這樣無法通過準(zhǔn)確的Id去獲取到相應(yīng)的Bean對象了
測試觀察
首先,如果要將指定的對象存放到Spring中,在Spring的配置文件中的掃描包路徑一定不能錯(cuò),這樣我們在這個(gè)包中所包含的類前加上【五大類注解】,就可以將對象存儲到Spring中的
<content:component-scan base-package="com.spring.demo"></content:component-scan>
然后我便在這個(gè)包下寫了個(gè)UserController
類,并且加上了【@Controller】注解,此時(shí)Spring在加載的時(shí)候就會存儲改對象
@Controller public class UserController { public void SayHello(){ System.out.println("do SayHello()"); } }
此時(shí)看到,我在App類中去獲取到了這個(gè)Bean對象,而且使用的是【名稱 + 類名】的形式,這種形式就可以防止Spring中存儲多個(gè)Bean對象而造成的沖突問題
但是呢,我就卡在了這里,不知道該去寫什么名稱?因?yàn)楦緵]有在Spring中寫明Id值
首先我想到的是這個(gè)名稱會不會就是類名呢?但是在我進(jìn)行嘗試之后卻發(fā)現(xiàn)并不是這樣,編譯器報(bào)出了異常說No bean named 'UserController' available
然后我又想到了Java的命名規(guī)范是【小駝峰】,一般去通過這個(gè)類實(shí)例化對象的時(shí)候都是將首字母進(jìn)行一個(gè)小寫,其余不變,于是當(dāng)我使用這個(gè)名稱進(jìn)行傳遞的時(shí)候,程序運(yùn)行就沒有問題了
那我首先猜測它的命名就是這樣規(guī)定的,但是有沒有特例呢?
此時(shí)我又去定義了一個(gè)類,將其類名取成了兩個(gè)大寫字母開頭的,看看這樣子的命名是否還會以【小駝峰】的形式去進(jìn)行轉(zhuǎn)換
@Controller public class SController { public void SayHello(){ System.out.println("do SayHello()"); } }
但是當(dāng)我在看運(yùn)行結(jié)果的時(shí)候,卻發(fā)現(xiàn)這樣小駝峰的形式似乎行不通了
但是當(dāng)我在將名稱改回【類名】的時(shí)候,卻發(fā)現(xiàn)又可以運(yùn)行了,這是為什么呢?里面的轉(zhuǎn)換規(guī)則又是怎樣的?這需要我再去研究一番??
原理探究
通過上面的測試可以看出,Spring對于這個(gè)Bean對象的命名轉(zhuǎn)換是存在一定規(guī)則的,因?yàn)?u>【在Spring中,約定大于俗成】
接下去我就通過查看Spring源碼的方式帶讀者來探究一下到底這個(gè)Spring內(nèi)部對于這個(gè)Bean的命名轉(zhuǎn)換規(guī)則是怎樣的,雖然Spring框架的代碼都是開源的,但是要精準(zhǔn)地找到對應(yīng)想要的代碼邏輯可不簡單,需要層層深入地進(jìn)行探訪
1、首先第一步,我們可以按兩下【shift】鍵,便會跳出IDEA的搜索框,在這個(gè)里面你可以去搜尋當(dāng)前項(xiàng)目中所有的類、接口,以查看它們的內(nèi)部實(shí)現(xiàn)。然后我便發(fā)現(xiàn)了一個(gè)類叫做AnnotationBeanNameGenerator
,翻譯一下即為【注釋Bean名稱生成器】,那我猜測命名規(guī)范的代碼邏輯可能就在這個(gè)類中
2、當(dāng)我們進(jìn)入到這個(gè)類后,就可以去尋找其對應(yīng)的方法了,那個(gè)方法是和BeanName
有關(guān)聯(lián)的,首先點(diǎn)擊右側(cè)的【結(jié)構(gòu)】我們便可以看到這個(gè)類中到底有哪些方法,那一看我們就可以觀察到有generateBeanName()
這個(gè)方法,點(diǎn)到對應(yīng)的方法后再進(jìn)行觀察,便發(fā)現(xiàn)其最后返回時(shí)又去調(diào)用了一個(gè)方法,于是我繼續(xù)按住Ctrl鍵點(diǎn)進(jìn)去
點(diǎn)進(jìn)去發(fā)現(xiàn)里面又是一個(gè)方法,一些復(fù)雜的邏輯其實(shí)就是以這樣一種嵌套的形式進(jìn)行的,各個(gè)類、接口之間的方法調(diào)來調(diào)去
然后看到這是下面的這個(gè)方法buildDefaultBeanName()
生成默認(rèn)Bean名稱
最后的話我們看到它在return的時(shí)候似乎又通過一個(gè)類名去調(diào)用了一個(gè)方法,然后傳入了這個(gè)ClassName,那我繼續(xù)點(diǎn)進(jìn)去后就發(fā)現(xiàn)我似乎已經(jīng)不處于Spring框架的源碼中了,而是來到了JDK中
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); }
我們可以點(diǎn)擊右上角的這個(gè)按鈕【選擇打開的文件】去找到這個(gè)類所對應(yīng)的位置
最后我這邊順騰摸瓜地去查找就看到這個(gè)類是java.deskop
包下的一個(gè)類,那么我們在查看Spring源碼的時(shí)候最終還是來到了JDK下,這個(gè)可以說明一點(diǎn):Bean的命名并不是亂取的,而是使用JDK的一個(gè)命名標(biāo)準(zhǔn)去進(jìn)行命名的
然后我們就可以去看看JDK中對于命名的規(guī)范到底是怎樣的??
可以看到很明顯的這里是有兩種情況,若是首字母和第二個(gè)字母都是大寫的話,那就返回原來的名稱;第二種情況則是將字符串首先轉(zhuǎn)換成了字符數(shù)組,然后再將第一位變成小寫
那看到這里的話其實(shí)我已經(jīng)是明白了,原來Spring對于Bean的這個(gè)命名規(guī)則是這樣的
總結(jié)一下
最后的話我們來總結(jié)一下本次查看源碼的收獲吧??
通過查看Spring的源碼我們進(jìn)入到了JDK中,經(jīng)過代碼的閱讀將Bean的命名轉(zhuǎn)換總結(jié)了以下兩點(diǎn)
默認(rèn)情況:使用原類名首字母小寫就能讀取到Bean對象特例:如果首字母和第二字母都是大寫的情況下,那么Bean名稱就是原類名
在學(xué)習(xí)Spring框架的過程中,初學(xué)者難免會遇到不理解的地方,因?yàn)镾pring是一個(gè)IoC容器,會通過DI依賴注入的形式幫我們自動地去管理對象,所以內(nèi)部的細(xì)節(jié)便不得而知,但我們可以通過【閱讀源碼】的方式來進(jìn)行理解,去看看大佬是怎么思考的??
到此這篇關(guān)于透過Spring源碼查看Bean的命名轉(zhuǎn)換規(guī)則的文章就介紹到這了,更多相關(guān)Bean命名轉(zhuǎn)換規(guī)則內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java運(yùn)行時(shí)數(shù)據(jù)區(qū)概述詳解
這篇文章主要介紹了Java運(yùn)行時(shí)數(shù)據(jù)區(qū)概述,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03javax.validation.constraints如何校驗(yàn)參數(shù)合法性
本文將深入探討javax.validation.constraints的基本用法和高級應(yīng)用,幫助讀者更好地理解和運(yùn)用這個(gè)強(qiáng)大的校驗(yàn)框架,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07詳解如何Java中實(shí)現(xiàn)Excel的注釋和批注
注釋及批注是?Excel?中比較常用的功能,這篇文章主要為大家詳細(xì)介紹了如何在Java中實(shí)現(xiàn)Excel的注釋和批注,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-12-12Eclipse中改變默認(rèn)的workspace的方法及說明詳解
eclipse中改變默然的workspace的方法有哪幾種呢?接下來腳本之家小編給大家介紹Eclipse中改變默認(rèn)的workspace的方法及說明,對eclipse改變workspace相關(guān)知識感興趣的朋友一起學(xué)習(xí)吧2016-04-04java web實(shí)現(xiàn)網(wǎng)上手機(jī)銷售系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了java web實(shí)現(xiàn)網(wǎng)上手機(jī)銷售系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08Java實(shí)現(xiàn)向數(shù)組里添加元素
這篇文章主要介紹了Java實(shí)現(xiàn)向數(shù)組里添加元素方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11springcloud config配置讀取優(yōu)先級過程詳解
這篇文章主要介紹了springcloud config配置讀取優(yōu)先級過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09