IOC的初始化過程

1.概述

簡(jiǎn)單來說IOC容器的初始化過程是通過refresh()方法來啟動(dòng)的,這個(gè)方法表示IOC容器的正式啟動(dòng)阐肤。具體來說這個(gè)啟動(dòng)主要包含BeanDefinition的Resource定位养涮、載入和注冊(cè)三個(gè)過程治专。

2.IOC啟動(dòng)流程說明
  • 第一個(gè)過程是Resource定位過程褥傍。 這個(gè) Resource定位指的是BeanDefinition的資源定位(例如我們平時(shí)Spring項(xiàng)目中配置的各種xml配置統(tǒng)一抽象為Resource資源),它由ResourceLoader通過統(tǒng)一的Resource接口來完成宋雏,這個(gè)Resource對(duì)這種形式的BeanDefinition的使用提供了統(tǒng)一接口芜飘。
  • 第二個(gè)過程是BeanDefinition的載入過程。 載入過程是把用戶定義好的Bean表示成IOC容器內(nèi)部的數(shù)據(jù)結(jié)構(gòu)即BeanDefinition磨总。BeanDefinition實(shí)際上就是POJO對(duì)象在IOC容器中的抽象嗦明,通過對(duì)BeanDefinition定義的數(shù)據(jù)結(jié)構(gòu),使IOC容器能夠方便的對(duì)POJO對(duì)象也就是Bean對(duì)象進(jìn)行管理蚪燕。
  • 第三個(gè)過程就是BeanDefinition的向IOC的注冊(cè)過程娶牌。 這個(gè)過程主要是通過BeanDefinitionRegistry接口完成實(shí)現(xiàn)的。注冊(cè)過程是把載入過程中解析得到的BeanDefinition向IOC容器進(jìn)行注冊(cè)馆纳。其實(shí)IOC內(nèi)部就是將解析得到的BeanDefinition注入到一個(gè)HashMap中去诗良,IOC容器就是通過這個(gè)HashMap持有這些BeanDefinition數(shù)據(jù)的。
3.源代碼解析

FileSystemXmlApplicationContext為例鲁驶,核心繼承關(guān)系為:

FileSystemXmlApplicationContext核心繼承關(guān)系
示例代碼為:
FileSystemXmlApplicationContext applicationContext = new FileSystemXmlApplicationContext("classpath:bean.xml")

當(dāng)我們執(zhí)行上面這行代碼的時(shí)候一個(gè)IOC的資源定位鉴裹、解析、注冊(cè)過程就被完成钥弯,下面我們就分析一下上述代碼的核心執(zhí)行流程径荔。

/**
     * Create a new FileSystemXmlApplicationContext, loading the definitions
     * from the given XML file and automatically refreshing the context.
     * @param configLocation file path
     * @throws BeansException if context creation failed
     */
    public FileSystemXmlApplicationContext(String configLocation) throws BeansException {
        this(new String[] {configLocation}, true, null);
    }

我們選用的構(gòu)造器為傳入一個(gè)資源文件路徑,實(shí)際調(diào)用的內(nèi)部構(gòu)造器為:

/**
     * Create a new FileSystemXmlApplicationContext with the given parent,
     * loading the definitions from the given XML files.
     * @param configLocations array of file paths
     * @param refresh whether to automatically refresh the context,
     * loading all bean definitions and creating all singletons.
     * Alternatively, call refresh manually after further configuring the context.
     * @param parent the parent context
     * @throws BeansException if context creation failed
     * @see #refresh()
     */
    public FileSystemXmlApplicationContext(
            String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
            throws BeansException {
        // 父容器設(shè)置
        super(parent);
        // 設(shè)置資源訪問路徑
        setConfigLocations(configLocations);
        // 刷新啟動(dòng)容器
        if (refresh) {
            refresh();
        }
    }

當(dāng)我們執(zhí)行refresh()方法的時(shí)候脆霎,我們的ApplicationContext高級(jí)上下文容器就已經(jīng)創(chuàng)建好了总处,我們進(jìn)入refresh()方法區(qū)查看具體執(zhí)行的邏輯:

@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // Prepare this context for refreshing.
        // 刷新啟動(dòng)前的準(zhǔn)備工作
        prepareRefresh();

        // Tell the subclass to refresh the internal bean factory.
        // 獲取Beanfatory->資源的定位和解析就是在此方法中執(zhí)行的
        //(1)AbstractApplicationContext#obtainFreshBeanFactory()
        //(2)AbstractApplicationContext#refreshBeanFactory()實(shí)際執(zhí)行子類
        //(3)AbstractRefreshableApplicationContext#refreshBeanFactory()的方法
        創(chuàng)建DefaultListableBeanFactory并loadBeanDefinitions`
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // Prepare the bean factory for use in this context.
        // 配置BeanFactory標(biāo)準(zhǔn)Context特征,比如 classloader睛蛛,后置處理等鹦马。
        prepareBeanFactory(beanFactory);

        try {
            // Allows post-processing of the bean factory in context subclasses.
            // 允許添加BeanFactoryProcessor來修改beanFactory,子類覆蓋方法做額外處理  
            postProcessBeanFactory(beanFactory);

            // Invoke factory processors registered as beans in the context.
            // 回調(diào) 上面收集到的所有的 BeanFactoryProcessor 了
            invokeBeanFactoryPostProcessors(beanFactory);

            // Register bean processors that intercept bean creation.
            // 注冊(cè)bean的處理器
            registerBeanPostProcessors(beanFactory);

            // Initialize message source for this context.
            // 國際化相關(guān)的初始化
            initMessageSource();

            // Initialize event multicaster for this context.
            // 初始化應(yīng)用事件的廣播
            initApplicationEventMulticaster();

            // Initialize other special beans in specific context subclasses.
            // 留給子類Context實(shí)現(xiàn)一些特殊處理的模板方法(模板方法留給子類實(shí)現(xiàn))
            onRefresh();

            // Check for listener beans and register them.
            // 注冊(cè)監(jiān)聽器
            registerListeners();

            // Instantiate all remaining (non-lazy-init) singletons.
            // 單例實(shí)例化
            finishBeanFactoryInitialization(beanFactory);

            // Last step: publish corresponding event.
            // 完成刷新-推送相應(yīng)的事件
            finishRefresh();
        }

        catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization - " +
                        "cancelling refresh attempt: " + ex);
            }

            // Destroy already created singletons to avoid dangling resources.
            destroyBeans();

            // Reset 'active' flag.
            cancelRefresh(ex);

            // Propagate exception to caller.
            throw ex;
        }

        finally {
            // Reset common introspection caches in Spring's core, since we
            // might not ever need metadata for singleton beans anymore...
            // 清理那些不需要的緩存數(shù)據(jù)
            resetCommonCaches();
        }
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末玖院,一起剝皮案震驚了整個(gè)濱河市菠红,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌难菌,老刑警劉巖试溯,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異郊酒,居然都是意外死亡遇绞,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門燎窘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來摹闽,“玉大人,你說我怎么就攤上這事褐健「堵梗” “怎么了澜汤?”我有些...
    開封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)舵匾。 經(jīng)常有香客問我俊抵,道長(zhǎng),這世上最難降的妖魔是什么坐梯? 我笑而不...
    開封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任徽诲,我火速辦了婚禮,結(jié)果婚禮上吵血,老公的妹妹穿的比我還像新娘谎替。我一直安慰自己,他們只是感情好蹋辅,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開白布钱贯。 她就那樣靜靜地躺著,像睡著了一般晕翠。 火紅的嫁衣襯著肌膚如雪喷舀。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天淋肾,我揣著相機(jī)與錄音,去河邊找鬼爸邢。 笑死樊卓,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的杠河。 我是一名探鬼主播碌尔,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼券敌!你這毒婦竟也來了唾戚?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤待诅,失蹤者是張志新(化名)和其女友劉穎叹坦,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體卑雁,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡募书,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了测蹲。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片莹捡。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖扣甲,靈堂內(nèi)的尸體忽然破棺而出篮赢,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布启泣,位于F島的核電站涣脚,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏种远。R本人自食惡果不足惜涩澡,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望坠敷。 院中可真熱鬧妙同,春花似錦、人聲如沸膝迎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽限次。三九已至芒涡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間卖漫,已是汗流浹背费尽。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留羊始,地道東北人旱幼。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像突委,于是被迫代替她去往敵國和親柏卤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

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