<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          實(shí)現(xiàn)一個(gè)簡(jiǎn)單的 Spring Bean 容器

          共 4624字,需瀏覽 10分鐘

           ·

          2022-11-22 03:01

          面對(duì)復(fù)雜的源碼,試著找到開(kāi)頭和結(jié)尾是一件非常具有挑戰(zhàn)的事。為了讓更多的初學(xué)者上手,從本文開(kāi)始,我們將通過(guò)實(shí)踐的方式帶領(lǐng)讀者逐步實(shí)現(xiàn) Spring 框架的核心鏈路和功能邏輯。

          簡(jiǎn)化上手、凸顯重點(diǎn)、摒棄冗余,讓更多的初學(xué)者都能在這場(chǎng)學(xué)習(xí)旅途中收獲滿滿。旅途即將開(kāi)始,你準(zhǔn)備好了嗎?

          ? 本文難度:★☆☆☆☆

          ? 本文重點(diǎn):基于 Spring Bean 容器的存儲(chǔ)功能和讀取功能,采用時(shí)間復(fù)雜度為O(log n) 的 HashMap 數(shù)據(jù)結(jié)構(gòu)進(jìn)行設(shè)計(jì)和實(shí)現(xiàn)。

          容器是什么

          Spring Bean 包含并管理應(yīng)用對(duì)象的配置和生命周期。從這個(gè)意義上講,它是一種用于承載對(duì)象的容器,開(kāi)發(fā)者可以設(shè)置每個(gè) Bean 對(duì)象是如何被創(chuàng)建的,以及它們是如何互相關(guān)聯(lián)、構(gòu)建和使用的。使用這些 Bean 對(duì)象可以創(chuàng)建一個(gè)單獨(dú)的實(shí)例,或者在需要時(shí)生成一個(gè)新的實(shí)例。

          如果將一個(gè) Bean 對(duì)象交給 Spring Bean 容器管理,則這個(gè) Bean 對(duì)象會(huì)以類似零件的方式被拆解,然后存儲(chǔ)到 Spring Bean 容器的定義中,便于 Spring Bean 容器管理,這相當(dāng)于把對(duì)象解耦。

          當(dāng)一個(gè) Bean 對(duì)象被定義和存儲(chǔ)后,會(huì)由 Spring Bean 容器統(tǒng)一進(jìn)行分配,這個(gè)過(guò)程包括 Bean 對(duì)象的初始化和屬性填充等。最終,我們可以完整地使用一個(gè)被實(shí)例化后的Bean 對(duì)象。

          本文將帶領(lǐng)讀者實(shí)現(xiàn)一個(gè)簡(jiǎn)單的 Spring Bean 容器,用于定義、存儲(chǔ)和獲取 Bean對(duì)象。

          簡(jiǎn)單容器設(shè)計(jì)

          我們將可以存儲(chǔ)數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)稱為容器,如 ArrayList、LinkedList、HashSet 等。但在 Spring Bean 容器中,需要一種可以用于存儲(chǔ)對(duì)象和使用對(duì)象名稱進(jìn)行便捷索引的數(shù)據(jù)結(jié)構(gòu),所以選擇 HashMap 數(shù)據(jù)結(jié)構(gòu)是最合適的,下面簡(jiǎn)單介紹 HashMap。

          HashMap 是一種基于擾動(dòng)函數(shù)、負(fù)載因子和紅黑樹(shù)轉(zhuǎn)換等技術(shù)形成的拉鏈尋址的數(shù)據(jù)結(jié)構(gòu),能讓數(shù)據(jù)更加均勻地分布在哈希桶,以及碰撞時(shí)形成的鏈表和紅黑樹(shù)上。HashMap 的數(shù)據(jù)結(jié)構(gòu)會(huì)最大限度地使整個(gè)數(shù)據(jù)讀取的復(fù)雜度范圍為 O(1) ~ O(n),也存在較多使用復(fù)雜度為 O(n) 的鏈表查找數(shù)據(jù)的情況。不過(guò),經(jīng)過(guò) 10 萬(wàn)個(gè)單詞數(shù)據(jù)的擾動(dòng)函數(shù)索引計(jì)算后,通過(guò)在尋址位置膨脹的方差穩(wěn)定性對(duì)比驗(yàn)證得出,使用擾動(dòng)函數(shù)的數(shù)據(jù)會(huì)更均勻地分布在各個(gè)哈希桶索引上,基于這些特性的 HashMap 非常適合用于實(shí)現(xiàn)Spring Bean 容器。

          另外,實(shí)現(xiàn)一個(gè)簡(jiǎn)單的 Spring Bean 容器,還需要完成 Bean 對(duì)象的定義、注冊(cè)和獲取 3 個(gè)基本步驟,如圖 1-1 所示。

          1.定義

          BeanDefifinition 是我們?cè)诓殚?Spring 源碼時(shí)經(jīng)常看到的一個(gè)類,如 singleton 屬性、prototype 屬性和 BeanClassName 類型等。這里的實(shí)現(xiàn)會(huì)采用更加簡(jiǎn)單的方法,只需要定義一個(gè) Object 類型用于存儲(chǔ)任意類型的對(duì)象。

          2.注冊(cè)

          注冊(cè)過(guò)程相當(dāng)于把數(shù)據(jù)存儲(chǔ)到 HashMap 中,現(xiàn)在 HashMap 中存儲(chǔ)的是被定義的Bean 對(duì)象的信息。

          3.獲取

          最后就是獲取對(duì)象。Bean 對(duì)象的名字就是 key。當(dāng) Spring Bean 容器初始化 Bean 對(duì)象后,Bean 對(duì)象就可以被直接獲取。按照上述設(shè)計(jì)過(guò)程,我們來(lái)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的 Spring Bean 容器。

          簡(jiǎn)單容器實(shí)現(xiàn)

          1.工程結(jié)構(gòu)

          spring-step-01└── src ├── main │ └── java │ └── cn.bugstack.springframework │ ├── BeanDefinition.java │ └── BeanFactory.java └── test └── java └── cn.bugstack.springframework.test ├── bean │ └── UserService.java └── ApiTest.java

          Spring Bean 容器中類的關(guān)系如圖 1-2 所示。

          Spring Bean 容器實(shí)現(xiàn) 的 內(nèi) 容 非 常 簡(jiǎn) 單, 僅 包 括 一 個(gè) 簡(jiǎn) 單 的 BeanFactory 類 和BeanDefifinition 類。這里的類名稱與 Spring 源碼中的類名稱一致,只是實(shí)現(xiàn)起來(lái)會(huì)相對(duì)簡(jiǎn)化一些。在后續(xù)的擴(kuò)展過(guò)程中,我們可以不斷地添加內(nèi)容。

          ? BeanDefifinition:用于定義 Bean 對(duì)象,它的實(shí)現(xiàn)方式是以一個(gè) Object 類型存儲(chǔ)對(duì)象。

          ? BeanFactory:代表 Bean 對(duì)象的工廠,可以將 Bean 對(duì)象的定義存儲(chǔ)到 Map 中以便獲取 Bean 對(duì)象。

          2Bean 對(duì)象的定義

          源碼詳見(jiàn):cn.bugstack.springframework.BeanDefifinition。

          public class BeanDefinition { private Object bean; public BeanDefinition(Object bean) { this.bean = bean; } public Object getBean() { return bean; }}


          在目前的 Bean 對(duì)象定義中,只有一個(gè) Object 類型,因?yàn)樗撬蓄愋偷母割悾梢源鎯?chǔ)任意類型的 Bean 對(duì)象。讀者可以參考 Spring 源碼中這個(gè)類的信息,其名稱都是一樣的。在后續(xù)章節(jié)的實(shí)現(xiàn)過(guò)程中,我們會(huì)逐步完善 BeanDefifinition 類對(duì) Bean 對(duì)象定義的相關(guān)屬性字段,如propertyValues、initMethodName、destroyMethodName、scope、beanClass等。

          3Bean 工廠

          源碼詳見(jiàn):cn.bugstack.springframework.BeanFactory。

          public class BeanFactory { private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(); public Object getBean(String name) { return beanDefinitionMap.get(name).getBean(); } public void registerBeanDefinition(String name, BeanDefinition beanDefinition) { beanDefinitionMap.put(name, beanDefinition); }}


          BeanFactory 類是用于生成和使用對(duì)象的 Bean 工廠,BeanFactory 類的實(shí)現(xiàn)過(guò)程包括Bean 對(duì)象的注冊(cè)和獲取,這里注冊(cè)的是 Bean 對(duì)象的定義信息。

          目前,BeanFactory 類的實(shí)現(xiàn)是非常簡(jiǎn)化的,但這種簡(jiǎn)化的實(shí)現(xiàn)卻是整個(gè) Spring Bean容器中關(guān)于 Bean 對(duì)象使用的最終體現(xiàn),只不過(guò)在實(shí)現(xiàn)過(guò)程中只展示出了基本的核心原理。在后續(xù)的補(bǔ)充實(shí)現(xiàn)中,這個(gè)類的內(nèi)容會(huì)不斷增加。

          容器使用測(cè)試

          1.事先準(zhǔn)備

          源碼詳見(jiàn):cn.bugstack.springframework.test.bean.UserService。

          public class UserService { public void queryUserInfo(){ System.out.println(" 查詢用戶信息 "); }}

          這里簡(jiǎn)單定義了一個(gè) UserService 對(duì)象類,方便后續(xù)對(duì) Spring Bean 容器進(jìn)行測(cè)試。

          2.測(cè)試實(shí)例

          源碼詳見(jiàn):cn.bugstack.springframework.test.ApiTest。

          @Testpublic void test_BeanFactory(){ // 1. 初始化 BeanFactory 接口 BeanFactory beanFactory = new BeanFactory(); // 2. 注冊(cè) Bean 對(duì)象 BeanDefinition beanDefinition = new BeanDefinition(new UserService()); beanFactory.registerBeanDefinition("userService", beanDefinition); // 3. 獲取 Bean 對(duì)象 UserService userService = (UserService) beanFactory.getBean("userService"); userService.queryUserInfo();}


          在單元測(cè)試中,主要包括初始化 BeanFactory 接口、注冊(cè) Bean 對(duì)象、獲取 Bean 對(duì)象 3 個(gè)步驟,在使用效果上貼近于 Spring 框架,但這里會(huì)更加簡(jiǎn)化一些。

          在注冊(cè) Bean 對(duì)象的過(guò)程中,這里直接把 UserService 類實(shí)例化后作為入?yún)⑿畔鬟f給 BeanDefifinition。在后續(xù)的代碼中,我們會(huì)將這部分內(nèi)容放入 Bean 工廠中實(shí)現(xiàn)。

          3.測(cè)試結(jié)果

          查詢用戶信息Process finished with exit code 0

          從測(cè)試結(jié)果中可以看到,目前的 Spring Bean 容器案例已經(jīng)有了雛形。

          本文總結(jié)

          關(guān)于 Spring Bean 容器的一個(gè)簡(jiǎn)單實(shí)現(xiàn)已經(jīng)完成了,這部分代碼相對(duì)簡(jiǎn)單,讀者稍加嘗試就可以實(shí)現(xiàn)這部分內(nèi)容。

          但對(duì)于學(xué)習(xí)知識(shí)的過(guò)程來(lái)說(shuō),寫(xiě)代碼只是最后的步驟,形成整體思路和設(shè)計(jì)方案才是更重要的。讀者只有厘清了思路,才能真正地理解代碼。

          學(xué)習(xí) Spring 源碼難嗎?

          難!

          • 難到有1~2年編程經(jīng)驗(yàn)的工程師,也不知道從哪里下手。

          • 大部分資料和書(shū)籍都是從一個(gè)知識(shí)點(diǎn)直接透析到內(nèi)核。

          • 沒(méi)有閱讀源碼經(jīng)驗(yàn)的小白,根本沒(méi)法如編寫(xiě)者般感同身受地學(xué)習(xí),看時(shí)如云里霧里,忘時(shí)如過(guò)眼云煙。

          為啥會(huì)這樣?

          因?yàn)?Spring產(chǎn)生太久了,源碼太大了,主干核心源碼外的繁枝末節(jié)太多太多。就像將一個(gè)沙發(fā)左移、套個(gè)沙發(fā)罩、蓋上一塊布,再鋪個(gè)小坐墊,沙發(fā)套、蓋布、坐墊對(duì)初學(xué)源碼的開(kāi)發(fā)者來(lái)說(shuō),并沒(méi)有那么重要,我們要了解的是最初的沙發(fā)、最開(kāi)始的木板,看看它的結(jié)構(gòu)、聞聞它的味道。

          所以,如果你真地想了解Spring 這個(gè)源碼級(jí)復(fù)雜框架的設(shè)計(jì)和實(shí)現(xiàn)精髓,就應(yīng)該像開(kāi)發(fā)一個(gè)項(xiàng)目一樣,從零寫(xiě)一遍。只有你寫(xiě)了這個(gè)項(xiàng)目,才能知道具體細(xì)節(jié)是如何處理的,各類設(shè)計(jì)是如何實(shí)現(xiàn)的。

          手寫(xiě)Spring

          獨(dú)樂(lè)不如眾樂(lè),小傅哥把手動(dòng)實(shí)現(xiàn)簡(jiǎn)單版 Spring 框架的內(nèi)容編寫(xiě)成書(shū),希望幫助更多的研發(fā)人員學(xué)習(xí)Spring 源碼,編寫(xiě)出有價(jià)值的源碼設(shè)計(jì)方案。

          從此,你多了一段“手寫(xiě)Spring”項(xiàng)目的學(xué)習(xí)經(jīng)歷:具備了復(fù)雜源碼的架構(gòu)設(shè)計(jì)能力、吸收了復(fù)雜場(chǎng)景分治和抽象的思想、我就是學(xué)會(huì)了復(fù)雜結(jié)構(gòu)中設(shè)計(jì)模式的運(yùn)用。

          地圖:框架全貌

          讀者在學(xué)習(xí)的過(guò)程中,可以參考書(shū)中Spring 框架地圖,通過(guò)全局的視角,可以更好地理解和學(xué)習(xí) Spring 框架的設(shè)計(jì)與開(kāi)發(fā)。


          69元包郵到家

          首發(fā)限時(shí)特惠,限量100本

          我的準(zhǔn)備到了到時(shí)候我看看

          瀏覽 23
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  成人欧美日韩 | 国产欧美草莓视频 | 围产精品久久久久久久妞妞 | 黄色大片网址 | 无码高清一区二区 |