01-Spring的啟動(dòng)過程分析

Spring的啟動(dòng)過程

本文的目的是記錄自己在學(xué)習(xí)Spring容器啟動(dòng)過程中的一些筆記寝受,以供后面復(fù)習(xí)柬甥,也希望可以給有需要的朋友提供一點(diǎn)幫助。本次分析所用的Spring版本為 5.1.4.RELEASE辽话。
首先我們從容器創(chuàng)建為入口扔役,逐漸深入容器的啟動(dòng)過程帆喇。

ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);

上面這行代碼大家應(yīng)該都很熟悉,通過這行代碼就可以完成IOC容器的初始化亿胸,讓Spring幫我們管理一切坯钦。下面我們就從AnnotationConfigApplicationContext這個(gè)類開始,一層一層解開Spring的神秘面紗侈玄。

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
        /**
        此處只是初始化了Bean Definition的reader和scanner
        this.reader = new AnnotatedBeanDefinitionReader(this);
        this.scanner = new ClassPathBeanDefinitionScanner(this);
        */
        this();
        // 此處只是將傳進(jìn)來的配置類(AppConfig.class注冊(cè)到BeanDefinitionMap中去)
        register(annotatedClasses);
        // 重點(diǎn)在refresh方法里面
        refresh();
    }

在前兩個(gè)方法中只是做了簡(jiǎn)單的初始化ioc容器所需的對(duì)象婉刀,此時(shí)ioc容器是空的,通過refresh方法會(huì)一次來解析beandefinition并產(chǎn)生對(duì)象裝入容器中拗馒,下面來分析refresh方法路星。

   // Prepare this context for refreshing.
   // 這個(gè)方法只是記錄了容器啟動(dòng)時(shí)間,設(shè)置容器為active狀態(tài),并無實(shí)際操作洋丐,不重要呈昔。
   prepareRefresh();
   // Tell the subclass to refresh the internal bean factory.
   // 此處只是給Bean Factory設(shè)置了一個(gè)SerializationId
   ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); 
   // Prepare the bean factory for use in this context.
   // 初始化了IOC容器的一些工具,比如Class Loader友绝、EL表達(dá)式解析器和屬性解析器
   prepareBeanFactory(beanFactory);
   // Allows post-processing of the bean factory in context subclasses.
   // 空方法
   postProcessBeanFactory(beanFactory);
   // Invoke factory processors registered as beans in the context.
   // 執(zhí)行所有的BeanFactoryPostProcessor
   // 在ConfigurationClassPostProcessor#processConfigBeanDefinitions()方法會(huì)對(duì)所有的配置類進(jìn)行處理堤尾,通過ConfigurationClassParser對(duì)象來解析,最終通過parser.parse(candidates);來調(diào)用解析方法迁客。
   // 其中會(huì)處理所有@Configuration注解的類郭宝,解析其配置的@Bean和@ComponentScan注解,將相關(guān)的Bean掃描并加入到BeanDefinitionMaps中掷漱,之后會(huì)使用動(dòng)態(tài)代理(CGLIB)增強(qiáng)Configuration類粘室,增強(qiáng)是直接修改Bean Definition中BeanClass屬性,直接替換為代理后的class
   invokeBeanFactoryPostProcessors(beanFactory);
   // 注冊(cè)了兩個(gè)BeanPostProcessor卜范,一個(gè)CommonBeanPostProcessor衔统,另一個(gè)AutoWiredBeanPostProcessor,注意,這個(gè)后置處理器很重要海雪,他是完成自動(dòng)裝配的關(guān)鍵锦爵!
   // Register bean processors that intercept bean creation.
   registerBeanPostProcessors(beanFactory);
   // Initialize message source for this context.
   // 像BeanFactory注冊(cè)了messageSource
   initMessageSource();
   // Initialize event multicaster for this context.
   // 向BeanFactory注冊(cè)了applicationEventMulticaster
   initApplicationEventMulticaster();
   // Initialize other special beans in specific context subclasses.
   // 空方法,api注釋中寫的是允許子類添加一些特定的邏輯在實(shí)例化單例Bean之前奥裸。 before instantiation of singletons.
   onRefresh();
   // Check for listener beans and register them.
   // 將實(shí)現(xiàn)了ApplicationListener的類注冊(cè)到applicationEventMulticaster中
   registerListeners();
   // Instantiate all remaining (non-lazy-init) singletons.
   // 實(shí)例化Bean DefinitionMap中所有的非懶加載的單例Bean
   // 前面做大堆準(zhǔn)備工作险掀,最終會(huì)凍結(jié)配置,防止配置發(fā)生變化(freezeConfiguration)湾宙,結(jié)束后調(diào)用preInstantiateSingletons()方法來實(shí)例化樟氢,由于實(shí)例化較為重要,下面單獨(dú)分析preInstantiateSingletons方法
   finishBeanFactoryInitialization(beanFactory);
   // Last step: publish corresponding event.
   // 結(jié)束啟動(dòng)過程创倔,會(huì)清空在初始化過程中創(chuàng)建的一些緩存嗡害,同時(shí)調(diào)用LifecycleProcessor#onRefresh方法。最后會(huì)發(fā)布ContextRefreshedEvent事件畦攘。
   finishRefresh();

以上就是Spring啟動(dòng)的全過程,后面我們會(huì)深入分析容器的初始化過程十电,容器如何解析配置類知押,如何根據(jù)配置類來實(shí)例化單例對(duì)象等。
由于本人水平有限鹃骂,難免遇到表述不清或錯(cuò)誤的情況台盯,如果存在任何問題,請(qǐng)大家及時(shí)提醒畏线,我會(huì)在第一時(shí)間進(jìn)行修正静盅。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蒿叠,更是在濱河造成了極大的恐慌明垢,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件市咽,死亡現(xiàn)場(chǎng)離奇詭異痊银,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)施绎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門溯革,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人谷醉,你說我怎么就攤上這事致稀。” “怎么了俱尼?”我有些...
    開封第一講書人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵抖单,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我号显,道長(zhǎng)臭猜,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任押蚤,我火速辦了婚禮蔑歌,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘揽碘。我一直安慰自己次屠,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開白布雳刺。 她就那樣靜靜地躺著劫灶,像睡著了一般。 火紅的嫁衣襯著肌膚如雪掖桦。 梳的紋絲不亂的頭發(fā)上本昏,一...
    開封第一講書人閱讀 51,541評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音枪汪,去河邊找鬼涌穆。 笑死,一個(gè)胖子當(dāng)著我的面吹牛雀久,可吹牛的內(nèi)容都是我干的宿稀。 我是一名探鬼主播,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼赖捌,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼祝沸!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤罩锐,失蹤者是張志新(化名)和其女友劉穎奉狈,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體唯欣,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嘹吨,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了境氢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蟀拷。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖萍聊,靈堂內(nèi)的尸體忽然破棺而出问芬,到底是詐尸還是另有隱情,我是刑警寧澤寿桨,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布此衅,位于F島的核電站,受9級(jí)特大地震影響亭螟,放射性物質(zhì)發(fā)生泄漏挡鞍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一预烙、第九天 我趴在偏房一處隱蔽的房頂上張望墨微。 院中可真熱鬧,春花似錦扁掸、人聲如沸翘县。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)锈麸。三九已至,卻和暖如春牺蹄,著一層夾襖步出監(jiān)牢的瞬間忘伞,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工沙兰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留虑省,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓僧凰,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親熟丸。 傳聞我的和親對(duì)象是個(gè)殘疾皇子训措,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355