日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

手写简版spring --2--实现Bean的定义、注册、获取

發(fā)布時(shí)間:2025/3/15 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 手写简版spring --2--实现Bean的定义、注册、获取 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、目標(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
    //在 Bean 定義類(lèi)中已經(jīng)把上一章節(jié)中的 Object bean 替換為 Class ,這樣就可以把Bean 的實(shí)例化操作放到容器中處理了。 //如果你有仔細(xì)閱讀過(guò)上一章并做了相應(yīng)的測(cè)試,那么你會(huì)發(fā)現(xiàn) Bean 的實(shí)例化操作是放在初始化調(diào)用階段傳遞給BeanDefinition 構(gòu)造函數(shù)的。 public class BeanDefinition {private Class beanClass;public BeanDefinition(Class beanClass) {this.beanClass = beanClass;}public Class getBeanClass() {return beanClass;}public void setBeanClass(Class beanClass) {this.beanClass = beanClass;} }
    • SingletonBeanRegistry
    // 單例注冊(cè)表//這個(gè)類(lèi)比較簡(jiǎn)單主要是定義了一個(gè)獲取單例對(duì)象的接口。 public interface SingletonBeanRegistry {Object getSingleton(String beanName); }
    • SingletonBeanRegistry
    //在 DefaultSingletonBeanRegistry 中主要實(shí)現(xiàn) getSingleton 方法,同時(shí)實(shí)現(xiàn)了一個(gè)受保護(hù)的 addSingleton 方法, //這個(gè)方法可以被繼承此類(lèi)的其他類(lèi)調(diào)用。包括:AbstractBeanFactory 以及繼承的 DefaultListableBeanFactory 調(diào)用。 public class cimplements SingletonBeanRegistry {private Map<String, Object> singletonObjects = new HashMap<>();@Overridepublic Object getSingleton(String beanName) {return singletonObjects.get(beanName);}protected void addSingleton(String beanName, Object singletonObject) {singletonObjects.put(beanName, singletonObject);} }
    • 抽象類(lèi)定義模板方法 (AbstarctBeanFactory)
    public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory {@Overridepublic Object getBean(String name) throws BeansException {Object bean = getSingleton(name);if (bean != null) {return bean;}BeanDefinition beanDefinition = getBeanDefinition(name);return createBean(name, beanDefinition);}protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;protected abstract Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException; }
    • 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
    public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory {@Overrideprotected Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException {Object bean = null;try {bean = beanDefinition.getBeanClass().newInstance();} catch (InstantiationException | IllegalAccessException e) {throw new BeansException("Instantiation of bean failed", e);}addSingleton(beanName, bean);return bean;} }
    • 在 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)
    public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements BeanDefinitionRegistry {private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();@Overridepublic void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {beanDefinitionMap.put(beanName, beanDefinition);}@Overridepublic BeanDefinition getBeanDefinition(String beanName) throws BeansException {BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);if (beanDefinition == null) throw new BeansException("No bean named '" + beanName + "' is defined");return beanDefinition;}}
    • 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)備
    public class UserService {public void queryUserInfo(){System.out.println("查詢(xún)用戶(hù)信息");} }
    • 測(cè)試
    @Test public void test_BeanFactory(){// 1.初始化 BeanFactoryDefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();// 2.注冊(cè) beanBeanDefinition beanDefinition = new BeanDefinition(UserService.class);beanFactory.registerBeanDefinition("userService", beanDefinition);// 3.第一次獲取 beanUserService userService = (UserService) beanFactory.getBean("userService");userService.queryUserInfo();// 4.第二次獲取 bean from SingletonUserService userService_singleton = (UserService) beanFactory.getBean("userService");userService_singleton.queryUserInfo(); }
    • 在此次的單元測(cè)試中除了包括;Bean 工廠、注冊(cè) Bean、獲取 Bean,三個(gè)步驟,還額外增加了一次對(duì)象的獲取和調(diào)用。這里主要測(cè)試驗(yàn)證單例對(duì)象的是否正確的存放到了緩存中。
    • 此外與上一章節(jié)測(cè)試過(guò)程中不同的是,我們把 UserService.class 傳遞給了 BeanDefinition 而不是像上一章節(jié)那樣直接 new UserService() 操作。]

    五、總結(jié)

  • 這一章已經(jīng)開(kāi)始復(fù)雜,各種接口抽象類(lèi)實(shí)現(xiàn)類(lèi)開(kāi)始出現(xiàn),牢牢記住:基本都是接口做出約定,抽象類(lèi)給出場(chǎng)景,子類(lèi)具體實(shí)現(xiàn),然后接口調(diào)用。
  • 在 Spring Bean 容器的實(shí)現(xiàn)類(lèi)中要重點(diǎn)關(guān)注類(lèi)之間的職責(zé)和關(guān)系,幾乎所有的程序功能設(shè)計(jì)都離不開(kāi)接口、抽象類(lèi)、實(shí)現(xiàn)、繼承,而這些不同特性類(lèi)的使用就可以非常好的隔離開(kāi)類(lèi)的功能職責(zé)和作用范圍。而這樣的知識(shí)點(diǎn)也是在學(xué)習(xí)手寫(xiě)Spring Bean 容器框架過(guò)程非常重要的知識(shí)。
  • 總結(jié)

    以上是生活随笔為你收集整理的手写简版spring --2--实现Bean的定义、注册、获取的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。