Spring源碼(七)-IOC中的那些設(shè)計(jì)模式

前言

接上一篇講下spring-ioc中的設(shè)計(jì)模式。Spring作為一款及其優(yōu)秀的框架董习,其代碼的編寫非常優(yōu)秀,里面采用了大量的設(shè)計(jì)模式爱只。下面我們一點(diǎn)點(diǎn)分析皿淋。
先簡單說下常見的設(shè)計(jì)模式

  • 1、工廠模式
  • 2宋距、單例模式
  • 3衰腌、策略模式
  • 4推正、裝飾器模式

參考:設(shè)計(jì)模式學(xué)習(xí)

1、工廠模式

【參考】:工廠模式的區(qū)別

1.1哑舒、定義

工廠模式可將Java對(duì)象的調(diào)用者從被調(diào)用者的實(shí)現(xiàn)邏輯中分離出來,調(diào)用者只需關(guān)心被調(diào)用者必須滿足的規(guī)則(接口)幻馁,而不必關(guān)心實(shí)例的具體實(shí)現(xiàn)過程散址。工廠模式由抽象產(chǎn)品(接口)乖阵、具體產(chǎn)品(實(shí)現(xiàn)類)、生產(chǎn)者(工廠類)三種角色組成预麸。

1.2瞪浸、Spring中工廠模式的應(yīng)用

Spring中在各種BeanFactory以及ApplicationContext創(chuàng)建中都用到了典型的工廠方法模式。ApplicationContext的設(shè)計(jì)圖如下吏祸,SpringBean的體系結(jié)構(gòu)比較復(fù)雜对蒲,頂級(jí)接口是BeanFactory;BeanFactory共有三個(gè)子接口:ListableBeanFactory贡翘、HierarchicalBeanFactory和AutowireCapableBeanFactory蹈矮,還有一個(gè)SimpleJndiBeanFactory實(shí)現(xiàn)類。這三個(gè)子接口集成了頂級(jí)接口并對(duì)BeanFactory的功能進(jìn)行了增強(qiáng)鸣驱,稱為二級(jí)接口泛鸟;ConfigurableBeanFactory對(duì)二級(jí)接口HierarchicalBeanFactory進(jìn)行了再次增強(qiáng),它還繼承了另一個(gè)外來的接口SingletonBeanRegistry踊东,可以被稱為三級(jí)接口北滥;ConfigurableListableBeanFactory是一個(gè)更強(qiáng)大的接口,繼承了上述的所有接口闸翅,稱為四級(jí)接口再芋。其余的為抽象類,實(shí)現(xiàn)了Spring Bean四級(jí)接口所定義的所有功能坚冀。

2济赎、單例模式

【參考】: 單例

2.1、定義

單例模式具有以下特點(diǎn):

  • 1记某、單例類只能有一個(gè)實(shí)例司训。
  • 2、單例類必須自己創(chuàng)建自己的唯一實(shí)例液南。
  • 3豁遭、單例類必須給所有其他對(duì)象提供這一實(shí)例

2.2 Spring中單例模式的使用

在Spring中,所有的bean默認(rèn)都是單例創(chuàng)建的贺拣。在創(chuàng)建bean的代碼中我們經(jīng)潮托唬看到Singleton這個(gè)單詞。下面我們通過代碼看看單例是怎么實(shí)現(xiàn)的譬涡。

【AbstractBeanFactory】
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
            @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
·············           
        //實(shí)例化依賴的bean之后可以實(shí)例化mbd本身了
        //單例模式的創(chuàng)建
        if (mbd.isSingleton()) {
            sharedInstance = getSingleton(beanName, () -> {
                try {
                    /**
                     *核心創(chuàng)建bean
                     */
                    return createBean(beanName, mbd, args);
                }
                catch (BeansException ex) {
                    // Explicitly remove instance from singleton cache: It might have been put there
                    // eagerly by the creation process, to allow for circular reference resolution.
                    // Also remove any beans that received a temporary reference to the bean.
                    destroySingleton(beanName);
                    throw ex;
                }
            });
            //真正的bean初始化處理
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
        }
···········             
}       

通過將工廠函數(shù)傳入getSingleton函數(shù)中闪幽,就可以獲得一個(gè)Bean單例。單例的生成是通過修改createBean函數(shù)的參數(shù)實(shí)現(xiàn)的涡匀,其中mbd是一個(gè)RootBeanDefinition類盯腌,它存儲(chǔ)了生成Bean實(shí)例所需要的信息。在createBean之中的代碼里陨瘩,程序調(diào)用實(shí)例化Bean的函數(shù)initializeBean

3腕够、策略模式

【參考】:策略模式

3.1 定義

在策略模式(Strategy Pattern)中级乍,一個(gè)類的行為或其算法可以在運(yùn)行時(shí)更改。這種類型的設(shè)計(jì)模式屬于行為型模式帚湘。在策略模式中玫荣,我們創(chuàng)建表示各種策略的對(duì)象和一個(gè)行為隨著策略對(duì)象改變而改變的 context 對(duì)象。策略對(duì)象改變 context 對(duì)象的執(zhí)行算法大诸。策略模式實(shí)際就是一堆算法族的封裝捅厂。

3.2 Spring中策略模式的應(yīng)用

當(dāng)bean需要訪問資源配置文件時(shí),Spring有兩種方式

  • 代碼中獲取Rescource實(shí)例
  • 依賴注入
    第一種方式需要獲取rescource資源的位置资柔,代碼中耦合性太高焙贷,而今我們一直使用注解,依賴注入的方式去獲取贿堰。這樣的話就無需修改程序辙芍,只改配置文件即可。
<beans> 
   <bean id="test" class="com.example.Test"> 
   <!-- 注入資源 --> 
      <property name="tmp" value="classpath:book.xml"/>
   </bean> 
</beans>

在依賴注入的過程中羹与,Spring會(huì)調(diào)用ApplicationContext 來獲取Resource的實(shí)例故硅。然而,Resource 接口封裝了各種可能的資源類型注簿,包括了:UrlResource契吉,ClassPathResource跳仿,F(xiàn)ileSystemResource等诡渴,Spring需要針對(duì)不同的資源采取不同的訪問策略。在這里菲语,Spring讓ApplicationContext成為了資源訪問策略的“決策者”妄辩。在資源訪問策略的選擇上,Spring采用了策略模式山上。當(dāng) Spring 應(yīng)用需要進(jìn)行資源訪問時(shí)眼耀,它并不需要直接使用 Resource 實(shí)現(xiàn)類,而是調(diào)用 ApplicationContext 實(shí)例的 getResource() 方法來獲得資源佩憾,ApplicationContext 將會(huì)負(fù)責(zé)選擇 Resource 的實(shí)現(xiàn)類哮伟,也就是確定具體的資源訪問策略,從而將應(yīng)用程序和具體的資源訪問策略分離開來妄帘。

ApplicationContext ctx = new Class PathXmlApplicationContext("bean.xml");
Resource res = ctx.getResource("book.xml");

上面的代碼中楞黄,Spring 將采用和 ApplicationContext 相同的策略來訪問資源。即: ApplicationContext 是 ClassPathXmlApplicationContext抡驼,則res 就是 ClassPathResource 實(shí)例鬼廓。若將代碼改為:

ApplicationContext ctx = new Class FileSystemXmlApplicationContext("bean.xml");

則再次調(diào)用ctx.getResource時(shí),res 就是 ClassPathResource 實(shí)例致盟。

4碎税、裝飾器模式

【參考】:裝飾器模式

4.1尤慰、定義

通過使用修飾模式,可以在運(yùn)行時(shí)擴(kuò)充一個(gè)類的功能雷蹂。原理是:增加一個(gè)修飾類包裹原來的類伟端,包裹的方式一般是通過在將原來的對(duì)象作為修飾類的構(gòu)造函數(shù)的參數(shù)。裝飾類實(shí)現(xiàn)新的功能萎河,但是荔泳,在不需要用到新功能的地方,它可以直接調(diào)用原來的類中的方法虐杯。修飾類必須和原來的類有相同的接口玛歌。

4.2、Spring中裝飾器模式的使用

Spring中類中帶有Wrapper的都是包裝類擎椰,如下創(chuàng)建bean就是典型的裝飾器模式

BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
    instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
    //根據(jù)指定的bean使用對(duì)應(yīng)的側(cè)臉創(chuàng)建新的實(shí)例支子,如工廠方法,構(gòu)造函數(shù)自動(dòng)注入达舒,簡單初始化
    instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;
if (beanType != null) {
    // Allow post-processors to modify the merged bean definition.
    synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            try {
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            }
            catch (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Post-processing of merged bean definition failed", ex);
            }
            mbd.postProcessed = true;
        }
    }
}

寫在最后

當(dāng)然Spring-IOC中還有很多的設(shè)計(jì)模式值朋,比如代理,代理模式會(huì)放到AOP源碼分析那里去講解巩搏,那里才是代理模式的大量使用昨登。
<iframe frameborder="no" border="0" marginwidth="0" marginheight="20" width=198 height=52 src="https://music.163.com/outchain/player?type=2&id=487587201&auto=1&height=32"></iframe>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市贯底,隨后出現(xiàn)的幾起案子丰辣,更是在濱河造成了極大的恐慌,老刑警劉巖禽捆,帶你破解...
    沈念sama閱讀 219,110評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件笙什,死亡現(xiàn)場離奇詭異,居然都是意外死亡胚想,警方通過查閱死者的電腦和手機(jī)琐凭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來浊服,“玉大人统屈,你說我怎么就攤上這事⊙捞桑” “怎么了愁憔?”我有些...
    開封第一講書人閱讀 165,474評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長述呐。 經(jīng)常有香客問我惩淳,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,881評(píng)論 1 295
  • 正文 為了忘掉前任思犁,我火速辦了婚禮代虾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘激蹲。我一直安慰自己棉磨,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,902評(píng)論 6 392
  • 文/花漫 我一把揭開白布学辱。 她就那樣靜靜地躺著乘瓤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪策泣。 梳的紋絲不亂的頭發(fā)上衙傀,一...
    開封第一講書人閱讀 51,698評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音萨咕,去河邊找鬼统抬。 笑死,一個(gè)胖子當(dāng)著我的面吹牛危队,可吹牛的內(nèi)容都是我干的聪建。 我是一名探鬼主播,決...
    沈念sama閱讀 40,418評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼茫陆,長吁一口氣:“原來是場噩夢啊……” “哼金麸!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起簿盅,我...
    開封第一講書人閱讀 39,332評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤挥下,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后挪鹏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體见秽,經(jīng)...
    沈念sama閱讀 45,796評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡愉烙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,968評(píng)論 3 337
  • 正文 我和宋清朗相戀三年讨盒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片步责。...
    茶點(diǎn)故事閱讀 40,110評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡返顺,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蔓肯,到底是詐尸還是另有隱情遂鹊,我是刑警寧澤,帶...
    沈念sama閱讀 35,792評(píng)論 5 346
  • 正文 年R本政府宣布蔗包,位于F島的核電站秉扑,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜舟陆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,455評(píng)論 3 331
  • 文/蒙蒙 一误澳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧秦躯,春花似錦忆谓、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至茎活,卻和暖如春昙沦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背载荔。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評(píng)論 1 272
  • 我被黑心中介騙來泰國打工桅滋, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人身辨。 一個(gè)月前我還...
    沈念sama閱讀 48,348評(píng)論 3 373
  • 正文 我出身青樓丐谋,卻偏偏與公主長得像,于是被迫代替她去往敵國和親煌珊。 傳聞我的和親對(duì)象是個(gè)殘疾皇子号俐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,047評(píng)論 2 355

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