如何編寫自己的Spring容器

? ? Spring是目前開發(fā)最為重要的后端框架,那么它運(yùn)行的基本邏輯是什么刑棵?又如何編寫一個自定義的Spring容器砚婆?

Spring是如何調(diào)用的意蛀?

? ? 我們在使用Spring的時(shí)候淆珊,第一步應(yīng)該是加載配置夺饲,常見的有XML配置文件形式和注解形式的,本次采用最常用的注解形式來編寫自定義Spring容器套蒂。從Spring加載的方式看钞支,需要一個上下文加載器茫蛹,把配置入口類作為參數(shù)傳入操刀。然后通過getBean方法獲取到bean實(shí)例,然后就可以調(diào)用實(shí)例里的方法了婴洼。如圖1所示:

圖1

Spring是如何加載文件的骨坑?

? ? Spring中定義指定掃描包路徑的注解是@ComponentScan,在指定了掃描包路徑后需要獲取哪些文件需要被加載柬采,那么這個時(shí)候就需要@Component注解了欢唾,在自定義注解中也同樣創(chuàng)建這兩個注解,注解中都定義一個參數(shù)粉捻,@ComponentScan參數(shù)代表掃描包的路徑礁遣,@Component參數(shù)代表beanName。如圖2所示肩刃,輸出的是@ComponentScan中的包路徑:

圖2

? ? 對于Java來說祟霍,加載的是class文件杏头,因此需要獲取class文件的相對路徑,需要把 . 轉(zhuǎn)換成 / 沸呐,然后再讀取文件醇王,獲取到文件后,再利用loadClass方法來反射構(gòu)造類崭添。用搜索@ComponentScan注解的方式對文件遍歷后寓娩,就能獲取到所有含@Component注解的類了,如圖3:

圖3

? ? 我們在進(jìn)行g(shù)etBean方法獲取bean實(shí)例的時(shí)候呼渣,傳入的是一個beanName棘伴,@Component在沒有傳入指定beanName的時(shí)候默認(rèn)使用的是類的小寫駝峰,可以調(diào)用jdk自帶的方法來生成徙邻,如圖4:

圖4

? ? BeanDefinition顧名思義是Bean定義排嫌,Spring在加載后把bean相關(guān)的所有信息都打包成一個BeanDefinition,自定義spring中就簡單點(diǎn)缰犁,里面的參數(shù)只定義兩個淳地,Class type代表bean所在類和String scope代表作用域。scope作用域一般分為單例和原型的帅容,單例bean不會重復(fù)創(chuàng)建颇象,而原型bean在每次注入或者通過上下文獲取的時(shí)候都會創(chuàng)建。同樣定義一個@Scope注解并徘,默認(rèn)singleton遣钳。為了后續(xù)能方便通過beanName獲取到Beandefinition,這邊同時(shí)定義一個beandefinitionMap麦乞,以beanName作為key蕴茴,BeanDefinition作為value。如圖5:

圖5

? ? ? ? 到目前為止姐直,模擬Spring對class文件的掃描就完成了倦淀。

Spring通過getBean獲取實(shí)例

? ? 通過圖1可以看到,我們是通過getBean方法声畏,傳入一個beanName來獲取bean實(shí)例的撞叽。要生成實(shí)例,就需要通過反射創(chuàng)建插龄,這時(shí)候就需要用到我們的BeanDefinition愿棋,首先需要判斷是單例還是原型,如果是原型的均牢,直接創(chuàng)建糠雨,如果是單例的,需要和之前創(chuàng)建的實(shí)例進(jìn)行比較徘跪,這時(shí)候就需要引入另一個實(shí)例參數(shù)singletonObjects甘邀,以beanName作為key砂竖,對應(yīng)創(chuàng)建的實(shí)例作為value,從這個參數(shù)中獲取不到實(shí)例才需要進(jìn)行創(chuàng)建鹃答,如圖6:

圖6

? ? 使用反射的形式通過class創(chuàng)建實(shí)例乎澄,自定義Spring容器采用無參構(gòu)造器構(gòu)建實(shí)例即可,如圖7:

? ??

圖7

? ??然后在掃描的時(shí)候测摔,遍歷一遍beanDefinitionMap置济,對其中的singleton生成實(shí)例,并塞進(jìn)singletonObjects中锋八,如圖8:

圖8

Spring的BeanPostProcessor

????Spring的BeanPostProcessor是在bean對象在實(shí)例化或者依賴注入完畢后浙于,調(diào)用自己方法的前后添加自己的邏輯,這個就是Spring的AOP挟纱,所以我們需要自定義一個BeanPostProcessor類羞酗,并編寫前置處理器方法和后置處理器方法,如圖9:


圖9

? ? 自定義的Spring在掃描的時(shí)候就應(yīng)該關(guān)注到BeanPostProcessor了紊服,正程垂欤可以通過new出你的BeanPostProcessor來執(zhí)行前置或者后置方法,但是也可以在掃描的時(shí)候就把實(shí)現(xiàn)了BeanPostProcessor的類所生成的實(shí)例存入beanPostProcessorList中以供在創(chuàng)建實(shí)例的時(shí)候執(zhí)行響應(yīng)的方法欺嗤,如圖10:

圖10

? ? 下圖11為如何使用自定義的BeanPostProcessor:


圖11

Spring的InitialzingBean

? ? Spring的InitializingBean是用來執(zhí)行相關(guān)的業(yè)務(wù)操作参萄,只需要實(shí)現(xiàn)它的afterPropertiesSet方法即可,在創(chuàng)建bean實(shí)例的時(shí)候煎饼,只需把它放在BeanPostProcessor的前置處理器和后置處理器之間即可讹挎,使用instance of來判斷是否實(shí)現(xiàn)了InitializingBean方法,如圖12和圖13:

圖12
圖13

Spring的@Autowired

? ? Spring中比較常用的還有一個@Autowired吆玖,用來做依賴注入筒溃,里面有個默認(rèn)的required參數(shù)表示是否開啟自動裝配,默認(rèn)為true沾乘,我們自定義的@Autowired就不加參數(shù)了怜奖,注解放置的位置也固定在字段上,就按照自動裝配去加載意鲸。

? ? 在創(chuàng)建實(shí)例的時(shí)候烦周,對實(shí)例中的字段逐個判斷有沒有@Autowired注解尽爆,若有怎顾,對field進(jìn)行set操作,將field對應(yīng)的bean實(shí)例注入進(jìn)來漱贱,替換掉之前的實(shí)例槐雾,調(diào)用的方法就是之前提到的getBean操作,但在自定義的Spring中簡化后就fieldName作為beanName傳入幅狮,后續(xù)可以自行優(yōu)化募强,如圖14:

圖14

? ? 此時(shí)就已經(jīng)完成了自定義Spring框架的基礎(chǔ)流程株灸。

? ? 源碼下載地址:https://github.com/LuoChen1996/identitify_spring.git

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市擎值,隨后出現(xiàn)的幾起案子慌烧,更是在濱河造成了極大的恐慌,老刑警劉巖鸠儿,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件屹蚊,死亡現(xiàn)場離奇詭異,居然都是意外死亡进每,警方通過查閱死者的電腦和手機(jī)汹粤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來田晚,“玉大人嘱兼,你說我怎么就攤上這事∠屯剑” “怎么了芹壕?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長接奈。 經(jīng)常有香客問我哪雕,道長,這世上最難降的妖魔是什么鲫趁? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任斯嚎,我火速辦了婚禮,結(jié)果婚禮上挨厚,老公的妹妹穿的比我還像新娘堡僻。我一直安慰自己,他們只是感情好疫剃,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布钉疫。 她就那樣靜靜地躺著,像睡著了一般巢价。 火紅的嫁衣襯著肌膚如雪牲阁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天壤躲,我揣著相機(jī)與錄音城菊,去河邊找鬼。 笑死碉克,一個胖子當(dāng)著我的面吹牛凌唬,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播漏麦,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼客税,長吁一口氣:“原來是場噩夢啊……” “哼况褪!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起更耻,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤测垛,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后秧均,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體赐纱,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年熬北,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了疙描。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡讶隐,死狀恐怖起胰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情巫延,我是刑警寧澤效五,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站炉峰,受9級特大地震影響畏妖,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜疼阔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一戒劫、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧婆廊,春花似錦迅细、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至宾舅,卻和暖如春统阿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背筹我。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工扶平, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人崎溃。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓蜻直,卻偏偏與公主長得像盯质,于是被迫代替她去往敵國和親袁串。 傳聞我的和親對象是個殘疾皇子概而,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評論 2 354

推薦閱讀更多精彩內(nèi)容