手写简版spring --2--实现Bean的定义、注册、获取
一、目標(biāo)
在上一章節(jié)我們初步依照 Spring Bean 容器的概念,實(shí)現(xiàn)了一個(gè)粗糙版本的代碼實(shí)現(xiàn)。那么本章節(jié)我們需要結(jié)合已實(shí)現(xiàn)的 Spring Bean 容器進(jìn)行功能完善,實(shí)現(xiàn) Bean 容器關(guān)于 Bean 對(duì)象的注冊(cè)和獲取。這一次我們把 Bean 的創(chuàng)建交給容器,而不是我們?cè)谡{(diào)用時(shí)候傳遞一個(gè)實(shí)例化好的 Bean 對(duì)象,另外還需要考慮單例對(duì)象,在對(duì)象的二次獲取時(shí)是可以從內(nèi)存中獲取對(duì)象的。此外不僅要實(shí)現(xiàn)功能還需要完善基礎(chǔ)容器框架的類(lèi)結(jié)構(gòu)體,否則將來(lái)就很難擴(kuò)容進(jìn)去其他的功能了。
二、設(shè)計(jì)
鑒于本章節(jié)的案例目標(biāo),我們需要將 Spring Bean 容器完善起來(lái),首先非常重要的一點(diǎn)是在 Bean 注冊(cè)的時(shí)候只注冊(cè)一個(gè)類(lèi)信息,而不會(huì)直接把實(shí)例化信息注冊(cè)到 Spring 容器中。那么就需要修改 BeanDefinition 中的屬性 Object 為 Class,接下來(lái)在需要做的就是在獲取 Bean 對(duì)象時(shí)需要處理 Bean 對(duì)象的實(shí)例化操作以及判斷當(dāng)前單例對(duì)象在容器中是否已經(jīng)緩存起來(lái)了。整體設(shè)計(jì)如下
以下內(nèi)容其實(shí)就是圍繞著Spring的容器需要有單例,緩存,實(shí)例化,異常這些功能展開(kāi)的
- 首先我們需要定義 BeanFactory 這樣一個(gè) Bean 工廠,提供 Bean 的獲取方法getBean(String name),之后這個(gè) Bean 工廠接口由抽象類(lèi)AbstractBeanFactory 實(shí)現(xiàn)。這樣使用模板模式的設(shè)計(jì)方式,可以統(tǒng)一收口通用核心方法的調(diào)用邏輯和標(biāo)準(zhǔn)定義,也就很好的控制了后續(xù)的實(shí)現(xiàn)者不用關(guān)心調(diào)用邏輯,按照統(tǒng)一方式執(zhí)行。那么類(lèi)的繼承者只需要關(guān)心具體方法的邏輯實(shí)現(xiàn)即可。
- 那么在繼承抽象類(lèi) AbstractBeanFactory 后的AbstractAutowireCapableBeanFactory 就可以實(shí)現(xiàn)相應(yīng)的抽象方法了,因?yàn)锳bstractAutowireCapableBeanFactory 本身也是一個(gè)抽象類(lèi),所以它只會(huì)實(shí)現(xiàn)屬于自己的抽象方法,其他抽象方法由繼承 AbstractAutowireCapableBeanFactory 的類(lèi)實(shí)現(xiàn)。這里就體現(xiàn)了類(lèi)實(shí)現(xiàn)過(guò)程中的各司其職,你只需要關(guān)心屬于你的內(nèi)容,不是你的內(nèi)容,不要參與。這一部分內(nèi)容我們會(huì)在代碼里有具體的體現(xiàn)
- 另外這里還有塊非常重要的知識(shí)點(diǎn),就是關(guān)于單例 SingletonBeanRegistry 的接口定義實(shí)現(xiàn),而 DefaultSingletonBeanRegistry 對(duì)接口實(shí)現(xiàn)后,會(huì)被抽象類(lèi)AbstractBeanFactory 繼承。現(xiàn)在 AbstractBeanFactory 就是一個(gè)非常完整且強(qiáng)大的抽象類(lèi)了,也能非常好的體現(xiàn)出它對(duì)模板模式的抽象定義。接下來(lái)我們就帶著這些設(shè)計(jì)層面的思考,去看代碼的具體實(shí)現(xiàn)結(jié)果
- 類(lèi)依賴(lài)圖
基本都是接口做出約定,抽象類(lèi)給出場(chǎng)景,子類(lèi)具體實(shí)現(xiàn),然后接口調(diào)用。
這一章節(jié)關(guān)于 Spring Bean 容器的功能實(shí)現(xiàn)與 Spring 源碼中還有不少的差距,但以目前實(shí)現(xiàn)結(jié)果的類(lèi)關(guān)系圖來(lái)看,其實(shí)已經(jīng)具備了一定的設(shè)計(jì)復(fù)雜性,這些復(fù)雜的類(lèi)關(guān)系設(shè)計(jì)在各個(gè)接口定義和實(shí)現(xiàn)以及在抽象類(lèi)繼承中都有所體現(xiàn),例如:
- BeanFactory 的定義由 AbstractBeanFactory 抽象類(lèi)實(shí)現(xiàn)接口的 getBean 方法
- 而AbstractBeanFactory 又繼承了實(shí)現(xiàn)了 SingletonBeanRegistry 的DefaultSingletonBeanRegistry 類(lèi)。這樣 AbstractBeanFactory 抽象類(lèi)就具備了單例 Bean的注冊(cè)功能。
- AbstractBeanFactory 中又定義了兩個(gè)抽象方法: getBeanDefinition(StringbeanName) 、 createBean(String beanName, BeanDefinition beanDefinition) ,而這兩個(gè)抽象方法分別由DefaultListableBeanFactory 、AbstractAutowireCapableBeanFactory 實(shí)現(xiàn)。
- 最終 DefaultListableBeanFactory 還會(huì)繼承抽象類(lèi)AbstractAutowireCapableBeanFactory 也就可以調(diào)用抽象類(lèi)中的 createBean 方法了。
通過(guò)最終的DefaultListableBeanfatory new出的對(duì)象beanFactory已經(jīng)具備了很多功能。
怎么設(shè)計(jì)還是體現(xiàn)一個(gè)最基本的原則:類(lèi)實(shí)現(xiàn)過(guò)程中的各司其職,你只需要關(guān)心屬于你的內(nèi)容,不是你的內(nèi)容,不要參與。
三、代碼實(shí)現(xiàn)
- 工程結(jié)構(gòu)
- BeanDefinition
- SingletonBeanRegistry
- SingletonBeanRegistry
- 抽象類(lèi)定義模板方法 (AbstarctBeanFactory)
- AbstractBeanFactory 首先繼承了 DefaultSingletonBeanRegistry ,也就具備了使用單例注冊(cè)類(lèi)方法。
- 接下來(lái)很重要的一點(diǎn)是關(guān)于接口 BeanFactory 的實(shí)現(xiàn),在方法 getBean 的實(shí)現(xiàn)過(guò)程中可以看到,主要是對(duì)單例 Bean 對(duì)象的獲取以及在獲取不到時(shí)需要拿到 Bean的定義做相應(yīng) Bean 實(shí)例化操作。那么 getBean 并沒(méi)有自身的去實(shí)現(xiàn)這些方法,而是只定義了調(diào)用過(guò)程以及提供了抽象方法,由實(shí)現(xiàn)此抽象類(lèi)的其他類(lèi)做相應(yīng)實(shí)現(xiàn)。
- 后續(xù)繼承抽象類(lèi) Abstrac tBeanFactory 的類(lèi)有兩個(gè),包括:AbstractAutowireCapableBeanFactory 、 DefaultListableBeanFactory ,這兩個(gè)類(lèi)分別做了相應(yīng)的實(shí)現(xiàn)處理,接著往下看。
- AbstractAutowireCapableBeanFactory
- 在 AbstractAutowireCapableBeanFactory 類(lèi)中實(shí)現(xiàn)了 Bean 的實(shí)例化操作newInstance ,其實(shí)這塊會(huì)埋下一個(gè)坑,有構(gòu)造函數(shù)入?yún)⒌膶?duì)象怎么處理 ?
- 在處理完 Bean 對(duì)象的實(shí)例化后,直接調(diào)用 addSingleton 方法存放到單例對(duì)象的緩存中去。
- 核心類(lèi)實(shí)現(xiàn) (DefaultListableBeanFactory)
- DefaultListableBeanFactory 在 Spring 源碼中也是一個(gè)非常核心的類(lèi),在我們目前的實(shí)現(xiàn)中也是逐步貼近于源碼,與源碼類(lèi)名保持一致。
- DefaultListableBeanFactory 繼承了 AbstractAutowireCapableBeanFactory 類(lèi),也就具備了接口 BeanFactory 和 AbstractBeanFactory 等一連串的功能實(shí)現(xiàn)。 所以有時(shí)候你會(huì)看到一些類(lèi)的強(qiáng)轉(zhuǎn),調(diào)用某些方法,也是因?yàn)槟銖?qiáng)轉(zhuǎn)的類(lèi)實(shí)現(xiàn)接口或繼承了某些類(lèi)。
- 除此之外這個(gè)類(lèi)還實(shí)現(xiàn)了接口 BeanDefinitionRegistry 中的registerBeanDefinition(String beanName, BeanDefinition beanDefinition) 方法,當(dāng)然你還會(huì)看到一個(gè) getBeanDefinition 的實(shí)現(xiàn),這個(gè)方法我們文中提到過(guò)它是抽象類(lèi) AbstractBeanFactory 中定義的抽象方法。 現(xiàn)在注冊(cè) Bean 定義與獲取 Bean 定義。就可以同時(shí)使用了,是不感覺(jué)這個(gè)套路還蠻深的。接口定義了注冊(cè),抽象類(lèi)定義了獲取,都集中在 DefaultListableBeanFactory 中的 beanDefinitionMap 里
四、測(cè)試
- 事先準(zhǔn)備
- 測(cè)試
- 在此次的單元測(cè)試中除了包括;Bean 工廠、注冊(cè) Bean、獲取 Bean,三個(gè)步驟,還額外增加了一次對(duì)象的獲取和調(diào)用。這里主要測(cè)試驗(yàn)證單例對(duì)象的是否正確的存放到了緩存中。
- 此外與上一章節(jié)測(cè)試過(guò)程中不同的是,我們把 UserService.class 傳遞給了 BeanDefinition 而不是像上一章節(jié)那樣直接 new UserService() 操作。]
五、總結(jié)
總結(jié)
以上是生活随笔為你收集整理的手写简版spring --2--实现Bean的定义、注册、获取的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 回首阿里10年产品经理路,1点忠告希望在
- 下一篇: 利用这些心理学效应,轻松拿到满意offe