spring源碼解析三(源碼閱讀先導(dǎo)篇)

上一期,我們簡(jiǎn)單分析了下spring的@Autowired注解的原理,這一次,我們?cè)俅畏治鰏pring的源碼,大家還接的我們最初使用spring的時(shí)候
都是要在配置文件配置bean,然后才能使用,現(xiàn)在慢慢的這個(gè)xml的配置方式已經(jīng)淘汰了,現(xiàn)在基本上都是使用springboot了,這次那,為了看
源碼方便,我們就從最開(kāi)始的配置文件加載來(lái)分析下

大家可以看到以下代碼,我將springApplication.run方法注釋掉了,就專(zhuān)門(mén)定義一個(gè)xml配置文件,然后加載這個(gè)配置文件,看看spring怎樣一步步
完成容器的創(chuàng)建,屬性賦值操作,等等

@SpringBootApplication
@MapperScan("com.ryx.xiaoxin_distribute.mapper")
@EnableCaching
@EnableTransactionManagement
public class XiaoxinDistributeApplication {


    public static void main(String[] args) {
        //SpringApplication.run(XiaoxinDistributeApplication.class, args);
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:application-hellospring.xml");

        System.out.println("applicationContext啟動(dòng)了....");

        // 從上下文中獲取bean
        HelloSpring helloSpring =  applicationContext.getBean(HelloSpringImpl.class);

        System.out.println(helloSpring.sayHello());
    }

}

#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" xmlns:jee="http://www.springframework.org/schema/jee"
       xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">

    <bean id="helloSpring" class="com.ryx.xiaoxin_distribute.spring.springIocAndAop.IOC.test1.HelloSpringImpl"/>
</beans>

在aplicationContext的繼承體系中,我們會(huì)發(fā)現(xiàn)aplicationContext繼承了BeanFactory,所以我們也可以說(shuō)ApplicationContext就是BeanFactory
BeanFactory到底是什么,你翻譯成Bean工廠,或者Bean容器,都沒(méi)有問(wèn)題,其實(shí)就是為我們生產(chǎn)各種我們需要的Bean,讓我們使用,在生產(chǎn)的過(guò)程中,
要處理各種依賴(lài)問(wèn)題,所以又引入了依賴(lài)注入,其實(shí)就是解決bean在生成我們需要的bean的時(shí)候?yàn)榱私鉀Q依賴(lài)問(wèn)題所產(chǎn)生的的一種處理方式
試想一下,在沒(méi)有BeanFactory的時(shí)候,對(duì)象之間的依賴(lài)關(guān)系,緊緊的耦合在一起,這種依賴(lài)關(guān)系必須我們自己維護(hù),然后就是各種new,但是spring出現(xiàn)之后
就告訴我們,你不用管各個(gè)類(lèi)之間的依賴(lài)了,我來(lái)幫你搞定,你只需要關(guān)注業(yè)務(wù)邏輯即可,還有一點(diǎn),最最重要的,我們終于可以不用new了,因?yàn)槎伎梢酝ㄟ^(guò)
beanFactory實(shí)例化好了,還有一點(diǎn),beanFctory在實(shí)例化bean的過(guò)程中(生命周期內(nèi)),為我們提供了各種街口,讓我們有能力在bean的生命周期內(nèi)為所欲為

總結(jié)下:
1:applicationContext就是一個(gè)beanFactory
2:beanFactory為我們解決了各個(gè)對(duì)象之間的依賴(lài)關(guān)系,達(dá)到松耦合的目的
3:我們不用在new對(duì)象了,
4:可以通過(guò)spring提供的各種接口在bean的生命周期內(nèi)對(duì)bean做各種啊操作

接下來(lái),我們跟著bean的啟動(dòng)來(lái)一探究竟

public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
        this(new String[] {configLocation}, true, null);
    }


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

        //初始化父類(lèi)content
        super(parent);
        //設(shè)置xml的配置路徑
        setConfigLocations(configLocations);
        //刷新上下文
        if (refresh) {
            refresh();
        }
    }

@Override
    public void refresh() throws BeansException, IllegalStateException {
        //使用同步鎖機(jī)制,防止容器并發(fā)刷新
        synchronized (this.startupShutdownMonitor) {
            //一: 預(yù)刷新操作,1:記錄容器啟動(dòng)的時(shí)間2:處理屬性的占位符3:校驗(yàn)屬性是否可以解析
            prepareRefresh();

            // 二:定義bean工廠解析xml文件中的bean內(nèi)容為map(BeandefinitionMap)的形式并將其注冊(cè)到beanFctory中于格式
                        //key:helloSprin value:com.ryx.xiaoxin_distribute.spring.springIocAndAop.IOC.test1.HelloSpringImpl
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // 三:設(shè)置類(lèi)加載器,手動(dòng)注冊(cè)系統(tǒng)屬性的bean
            prepareBeanFactory(beanFactory);

            try {
                //四:加載BeanFactoryPostProcessor ,對(duì)bean工廠執(zhí)行后置處理
                postProcessBeanFactory(beanFactory);

                // 五:加載實(shí)現(xiàn)了beanFactoryPostProcessors的方法
                invokeBeanFactoryPostProcessors(beanFactory);

                // 六:注冊(cè)并實(shí)例化所有實(shí)現(xiàn)了BeanPostProcessor接口的實(shí)現(xiàn)類(lèi)
                registerBeanPostProcessors(beanFactory);

                // 七:初始化MessageSource
                initMessageSource();

                // 八:為此上下文初始化事件多播器
                initApplicationEventMulticaster();

                //九:在特定上下文子類(lèi)中初始化其他特殊bean
                onRefresh();

                // 十:注冊(cè)監(jiān)聽(tīng)器bean
                registerListeners();

                // 十一:初始化所有的單例bean
                finishBeanFactoryInitialization(beanFactory);

                // 十二:發(fā)布相應(yīng)的事件,初始化完成
                finishRefresh();
            }

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

                // 十三:
                destroyBeans();

                // 十四:
                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...
                resetCommonCaches();
            }
        }
    }

可以看到,spring的12個(gè)比較重要的方法,我都簡(jiǎn)單注明了下屬性,本想在一篇文章寫(xiě)完這些步驟,但是內(nèi)容實(shí)在太多,我會(huì)按照一個(gè)步驟一篇文章的形式,來(lái)分析spring的源碼,希望我的文章會(huì)對(duì)你有一點(diǎn)點(diǎn)的幫助,本期文章是一個(gè)先導(dǎo)片,下一篇開(kāi)始,我會(huì)具體分析spring的步驟哈!
Thanks!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末配猫,一起剝皮案震驚了整個(gè)濱河市鱼鼓,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌歇终,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,729評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件北滥,死亡現(xiàn)場(chǎng)離奇詭異员串,居然都是意外死亡喷屋,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)月褥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)弛随,“玉大人,你說(shuō)我怎么就攤上這事宁赤∫ㄍ福” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,461評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵决左,是天一觀的道長(zhǎng)愕够。 經(jīng)常有香客問(wèn)我,道長(zhǎng)佛猛,這世上最難降的妖魔是什么惑芭? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,135評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮挚躯,結(jié)果婚禮上强衡,老公的妹妹穿的比我還像新娘。我一直安慰自己码荔,他們只是感情好漩勤,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著缩搅,像睡著了一般越败。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上硼瓣,一...
    開(kāi)封第一講書(shū)人閱讀 52,736評(píng)論 1 312
  • 那天究飞,我揣著相機(jī)與錄音,去河邊找鬼堂鲤。 笑死亿傅,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的瘟栖。 我是一名探鬼主播葵擎,決...
    沈念sama閱讀 41,179評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼半哟!你這毒婦竟也來(lái)了酬滤?” 一聲冷哼從身側(cè)響起签餐,我...
    開(kāi)封第一講書(shū)人閱讀 40,124評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎盯串,沒(méi)想到半個(gè)月后氯檐,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,657評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡体捏,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評(píng)論 3 342
  • 正文 我和宋清朗相戀三年冠摄,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片译打。...
    茶點(diǎn)故事閱讀 40,872評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡耗拓,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出奏司,到底是詐尸還是另有隱情乔询,我是刑警寧澤,帶...
    沈念sama閱讀 36,533評(píng)論 5 351
  • 正文 年R本政府宣布韵洋,位于F島的核電站竿刁,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏搪缨。R本人自食惡果不足惜食拜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望副编。 院中可真熱鬧负甸,春花似錦、人聲如沸痹届。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,700評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)队腐。三九已至蚕捉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間柴淘,已是汗流浹背迫淹。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,819評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留为严,地道東北人敛熬。 一個(gè)月前我還...
    沈念sama閱讀 49,304評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像第股,于是被迫代替她去往敵國(guó)和親荸型。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評(píng)論 2 361