Spring Bean的生命周期-實例化ApplicationContext(一)

Spring Bean的生命周期往深入去看,不是簡單的幾句話能講完阳懂,早就想寫相關的內容,但一直覺得工作量不會低柜思,就沒有動筆寫岩调。拆成幾篇來寫,這樣也不好給自己太大的壓力赡盘。

image.png

主要分析号枕,Spring容器的初始化過程,然后如何獲取Bean陨享,到最終銷毀Bean整個過程經(jīng)歷了什么東西葱淳。

代碼

主要為了分析,更多的是深入源代碼中抛姑,代碼寫的就簡單一些

//SpringApp.java文件
public class SpringApp {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("app.xml");
        HelloWorld hello = (HelloWorld) applicationContext.getBean("hello");
        hello.sayHello();
        applicationContext.close();
    }
}

//HelloWorld 文件
public class HelloWorld {
    public void sayHello(){
        System.out.println("hello World");
    }
}

//app.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="hello" class="me.aihe.HelloWorld">

    </bean>
</beans>

文件結構就是這個簡單赞厕,如下

image.png

過程分析

  1. 新建ClassPathXmlApplicationContext實例的時候,最終實例化的構造方法如下
  • configLocations配置文件位置定硝,支持字符串數(shù)組
  • refresh是否自動的刷新上下文皿桑,否則在配置之后要手動的調用refresh方法
  • parent 父級的上下文

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
            throws BeansException {

        super(parent);
        setConfigLocations(configLocations);
        if (refresh) {
            refresh();
        }
    }
        

其最終的實例化的父類為:

   //創(chuàng)建AbstractApplicationContext
    public AbstractApplicationContext() {
        this.resourcePatternResolver = getResourcePatternResolver();
    }

    public AbstractApplicationContext(ApplicationContext parent) {
        this();
        setParent(parent);
    }
    
    protected ResourcePatternResolver getResourcePatternResolver() {
        return new PathMatchingResourcePatternResolver(this);
    }
  1. 設置配置文件的位置, setConfigLocation(String location)
   //支持可變參數(shù),如果locations不存在蔬啡,那么默認為null
    public void setConfigLocations(String... locations) {
        if (locations != null) {
            Assert.noNullElements(locations, "Config locations must not be null");
            this.configLocations = new String[locations.length];
            //處理配置文件的位置诲侮,稍作處理
            for (int i = 0; i < locations.length; i++) {
                this.configLocations[i] = resolvePath(locations[i]).trim();
            }
        }
        else {
            this.configLocations = null;
        }
    }

  1. 刷新Context, 調用refresh()方法星爪,這里先貼出來整個方法浆西, Refreash方法是容器中非常重要的一個方法,一時間這里不好完全講說明白顽腾,先把每個方法的用途注釋寫上近零,接下來我們再一起看看其內部是怎么回事
public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // 準備刷新的Context.
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            // 告訴子類刷新內部的Bean Factory
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            // 準備好Context使用的Bean Factory
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses.
                // 設置Bean的 postPorcess
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                // 調用BeanFactory的 postProcess
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                // 注冊Bean的PostProcess
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                //對上下文中的消息源進行初始化
                initMessageSource();

                // Initialize event multicaster for this context.
                //初始化上下文的事件機制
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                //初始化其它特殊的beans
                onRefresh();

                // Check for listener beans and register them.
                //檢查這些Bean诺核,并且向容器注冊
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                //實例化所有的非懶加載的 Singleton
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                // 發(fā)布相關的事件
                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.
                // 銷毀已經(jīng)創(chuàng)建的singletons避免對資源產生不好的影響
                destroyBeans();

                // Reset 'active' flag.
                //重置 active 標志
                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...
                //重置所有的caches
                resetCommonCaches();
            }
        }
    }
涉及到類
  • PathMatchingResourcePatternResolver
  • StandardEnvironment
TODO
  • AbstractRefreshableConfigApplicationContext.resolvePath,其中涉及到了Environment.resolveRequiredPlaceholders(String path)

最后

讀代碼久信,如果條理清晰窖杀,是一件比較爽的工作,盡量不要急功近利裙士,我們一步一步來入客,壓力都會比較小一點。

參考

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末腿椎,一起剝皮案震驚了整個濱河市桌硫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌啃炸,老刑警劉巖铆隘,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異南用,居然都是意外死亡膀钠,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進店門裹虫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來肿嘲,“玉大人,你說我怎么就攤上這事筑公■撸” “怎么了?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵十酣,是天一觀的道長涩拙。 經(jīng)常有香客問我际长,道長耸采,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任工育,我火速辦了婚禮虾宇,結果婚禮上,老公的妹妹穿的比我還像新娘如绸。我一直安慰自己嘱朽,他們只是感情好,可當我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布怔接。 她就那樣靜靜地躺著搪泳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪扼脐。 梳的紋絲不亂的頭發(fā)上岸军,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天奋刽,我揣著相機與錄音,去河邊找鬼艰赞。 笑死佣谐,一個胖子當著我的面吹牛,可吹牛的內容都是我干的方妖。 我是一名探鬼主播狭魂,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼党觅!你這毒婦竟也來了雌澄?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤杯瞻,失蹤者是張志新(化名)和其女友劉穎掷伙,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體又兵,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡任柜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了沛厨。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片宙地。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖逆皮,靈堂內的尸體忽然破棺而出宅粥,到底是詐尸還是另有隱情,我是刑警寧澤电谣,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布秽梅,位于F島的核電站,受9級特大地震影響剿牺,放射性物質發(fā)生泄漏企垦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一晒来、第九天 我趴在偏房一處隱蔽的房頂上張望钞诡。 院中可真熱鬧,春花似錦湃崩、人聲如沸荧降。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽朵诫。三九已至,卻和暖如春薄扁,著一層夾襖步出監(jiān)牢的瞬間剪返,已是汗流浹背瞎领。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留随夸,地道東北人九默。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像宾毒,于是被迫代替她去往敵國和親驼修。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理诈铛,服務發(fā)現(xiàn)乙各,斷路器,智...
    卡卡羅2017閱讀 134,628評論 18 139
  • 1.1 Spring IoC容器和bean簡介 本章介紹了Spring Framework實現(xiàn)的控制反轉(IoC)...
    起名真是難閱讀 2,577評論 0 8
  • 本文是我自己在秋招復習時的讀書筆記幢竹,整理的知識點耳峦,也是為了防止忘記,尊重勞動成果焕毫,轉載注明出處哦蹲坷!如果你也喜歡,那...
    波波波先森閱讀 12,284評論 6 86
  • 1.1 spring IoC容器和beans的簡介 Spring 框架的最核心基礎的功能是IoC(控制反轉)容器邑飒,...
    simoscode閱讀 6,702評論 2 22
  • 她這樣/我也不懂了 可是/你不是最了解她的嗎
    religiousi閱讀 181評論 0 1