溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何構(gòu)建Spring源碼運(yùn)行環(huán)境

發(fā)布時(shí)間:2021-06-26 09:31:35 來源:億速云 閱讀:207 作者:chen 欄目:大數(shù)據(jù)

本篇內(nèi)容主要講解“如何構(gòu)建Spring源碼運(yùn)行環(huán)境”,感興趣的朋友不妨來看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“如何構(gòu)建Spring源碼運(yùn)行環(huán)境”吧!

為什么研究Spring源碼

自己研究源碼的初心就是想看看那些牛逼的框架到底是有多牛逼,代碼到底有多優(yōu)雅,怎么利用設(shè)計(jì)模式去構(gòu)建程序,如何漂亮實(shí)現(xiàn)解耦,如何設(shè)計(jì)擴(kuò)展點(diǎn)靈活讓第三方開發(fā)者干預(yù)框架的運(yùn)行,如何與框架進(jìn)行整合。說出來可能有人還不信,個(gè)人并不是因?yàn)橄肴AT這些大廠而研究源碼,估計(jì)像我這個(gè)年齡別人也不會(huì)要了。。。自嘲一下!

希望自己通過閱讀Spring源碼提高如下能力:

1.首先肯定是閱讀源代碼的能力,找到閱讀源碼的基本方法,提高DEBUG的能力,加強(qiáng)如何定位問題的技巧

2.讓自己心里的大象邁出一小步,讓自己熟悉閱讀源碼,培養(yǎng)習(xí)慣,以后看更多的源碼

3.從源碼中找到寫出漂亮代碼的底層邏輯,比如設(shè)計(jì)模式、如何解耦、優(yōu)雅的語法或者API、非常棒的工具類

4.提高項(xiàng)目腳手架質(zhì)量,提升編碼能力,加快BUG定位速度

5.將閱讀源碼的結(jié)果分享出來,盡量可以讓路過的人可以產(chǎn)生閱讀源碼的興趣,解決工作中遇到問題

構(gòu)建Spring源碼

最新的Spring源碼是通過Gradle構(gòu)建的,因此只接觸過Maven構(gòu)建的朋友建議花幾個(gè)小時(shí)在網(wǎng)上找一個(gè)Gradle的學(xué)習(xí)視頻,大概了解一下grovvy和Gradle相關(guān)知識(shí),不然真的看不懂gradle.build文件。比如閉包、Gradle特有的API等,還有Gradle的安裝、IDEA如何提升Gradle編譯速度等。

基于自己的環(huán)境寫了一篇博客:https://my.oschina.net/u/3049601/blog/3113019 歡迎參考

準(zhǔn)備工作

1.簡(jiǎn)單學(xué)習(xí)grovvy和Gradle相關(guān)知識(shí)

2.了解一下設(shè)計(jì)模式,比如裝飾者、模板方法、工廠方法,還有抽象類、接口的運(yùn)用,里面用了大量的設(shè)計(jì)模式,不提前了解一下,代碼看起來比較吃力

3.學(xué)習(xí)Java8的Lamda表達(dá)式

4.學(xué)習(xí)Idea的快捷鍵,DEBUG的一些技巧

如何去看Spring源碼

等Spring源碼構(gòu)建完成后,該如何著手去看喃,當(dāng)然是寫一個(gè)工程,通過DEBUG Spring源碼看執(zhí)行過程等,總結(jié)自己看源碼幾點(diǎn)經(jīng)驗(yàn)

1.一定要從GIT上下載源碼并構(gòu)建,反編譯看源碼,特別是復(fù)雜的代碼會(huì)發(fā)蒙的。

2.在工程中開啟新的工程或者module,引用項(xiàng)目中的module進(jìn)行調(diào)試

3.看源碼之前一定要對(duì)框架的使用比較熟悉,千萬不要對(duì)框架的使用都不熟悉就跑去看源碼,那樣一定會(huì)發(fā)蒙的。所以花點(diǎn)錢買點(diǎn)框架使用的書或者視頻先看看,不要吝嗇那幾分錢,等你看完工資一定會(huì)漲的。比如SpringMVC,你就只知道加@Controller @Service @Component完成業(yè)務(wù)代碼可不行。

4.看源碼時(shí)通過DEBUG對(duì)框架有總體上的認(rèn)識(shí),不要一來就往深、細(xì)了摳,如果那樣的話,你會(huì)發(fā)現(xiàn)自己很快就看不下去了

5.DEBUG時(shí)著重先關(guān)注每行代碼執(zhí)行完后關(guān)鍵變量的變化,比如Spring源碼當(dāng)中的beanDefinitionMap singletonObjects beanPostProcessors等,返回的對(duì)象或者值是不是可能你需要關(guān)注的

6.善用DEBUG的條件斷點(diǎn),否則可能你按了無數(shù)次F6也到不了你關(guān)注的觸發(fā)點(diǎn)或者執(zhí)行點(diǎn)

7.一定要邊看邊加注釋、做筆記、畫圖什么的,因?yàn)橐粌商炷闶强床煌甑?,很可能因?yàn)槠渌虑榈R了,等下次來看又蒙了

8.GOOGLE 百度是常用工具,也可以試著搜索一下gitee或者github上面是否已經(jīng)有別人看過的源碼分析的項(xiàng)目,DOWN下來接著看,可以提高閱讀速度,但是一定要寫代碼去驗(yàn)證,因?yàn)橛腥酥苯臃g的英文,也許那并沒有什么Luan用。既然是看源碼,是基本的東西,凡是別人的東西一定要多方面驗(yàn)證才能吸收成正確的自己的,否則看了半天結(jié)果是錯(cuò)的就麻煩了。我就遇到了這樣的問題,在搜索引擎上找到的內(nèi)容其實(shí)在Spring5已經(jīng)變了。

Spring大概的工作流程

開始王婆賣瓜。。。。因?yàn)楝F(xiàn)在開發(fā)都是基于注解的,因此也是拿AnnotationConfigApplicationContext作為分析對(duì)象

概要流程

如何構(gòu)建Spring源碼運(yùn)行環(huán)境

非常概要的圖描述Spring容器初始化過程

Spring核心類實(shí)例化

    核心類起的作用就好像汽車的發(fā)動(dòng)機(jī),沒它都跑不了咯,還能指望它帶你去撩妹、看帥哥么。同樣,Spring的核心類能夠保證容器或者叫上下文能夠正常工作,基于它管理我們的業(yè)務(wù)對(duì)象,實(shí)現(xiàn)業(yè)務(wù)邏輯,比如:

    AnnotationConfigApplicationContext:也就是Spring的整個(gè)容器,Spring還有另外一個(gè)類似的叫ClassPathXmlApplicatonContext(基于XML配置的),在它里面包含了所有實(shí)例化的單例Bean、系統(tǒng)參數(shù)與配置文件加載后的鍵值對(duì)、后置處理器、每個(gè)Bean的定義等等

    AnnotatedBeanDefinitionReader:負(fù)責(zé)讀取被注解修飾了的Bean的定義,并添加到某一個(gè)Bean定義的集合當(dāng)中。典型的場(chǎng)景就是我的ImportResourceAppConfig.class傳入到AnnotatedBeanDefinitionReader.register()方法中,在BeanDefinitionMap中會(huì)新增一個(gè)對(duì)應(yīng)的元素。

    DefaultListableBeanFactory:這個(gè)就相當(dāng)相當(dāng)重要了。。。它包含了注冊(cè)BeanDefinition-registerBeanDefinition(),然后利用BeanDefinition獲取或者創(chuàng)建Bean的邏輯-getBean(),對(duì)應(yīng)的就有兩個(gè)方法常使用的四個(gè)變量:

        private final Map<String, BeanDefinition> beanDefinitionMap;--存放所有的Spring Bean定義(BeanDefinition),關(guān)于BeanDefinition詳解查看:https://my.oschina.net/u/3049601/blog/3127635

        private final Map<String, Object> singletonObjects                    --存放所有的單例Spring Bean

        private final Map<String, Object> earlySingletonObjects            --存放循環(huán)依賴時(shí)需要提前被暴露的Bean,這些Bean并沒有被很多PostProcessor(中文翻譯為后置處理器)處理,以解決循環(huán)依賴不會(huì)出現(xiàn)無限制的遞歸(這里沒明白沒關(guān)系,知道它和解決循環(huán)依賴有很重要關(guān)系即可,后面會(huì)詳細(xì)說明)

        private final Set<String> singletonsCurrentlyInCreation              --存放當(dāng)前容器中正在被創(chuàng)建的beanName(它也和循環(huán)依賴有很大關(guān)系)

核心組件類定義的注冊(cè)

    圖中的就是Bean定義集合的元素截圖,這些組件會(huì)完成@ComponentScan注解的包掃描,以及被掃描到的類定義注冊(cè),實(shí)例化裸對(duì)象,完成SpringBean的初始化(包含了各種PostProcessor的處理,比如依賴注入)

如何構(gòu)建Spring源碼運(yùn)行環(huán)境

    圖中截圖Map中Key對(duì)應(yīng)的類如下順序:

    ConfigurationClassPostProcessor:掃描@ComponentScan中指定包路徑下所有符合Spring規(guī)則的類,如加了@Configuration @Component等的類,將他們的BeanDefinition注冊(cè)到beanDefinitionMaps當(dāng)中。還有另外一個(gè)功能就是添加一個(gè)ImportAwareBeanPostProcessor,它可以讓你的Bean獲取到將@Import作為元注解時(shí)自定義注解的屬性鍵值對(duì)(此功能可以先不管)

    DefaultEventListenerFactory:和Application Event有關(guān),還沒詳細(xì)查看以后再補(bǔ)充

    EventListenerMethodProcessor:和Application Event有關(guān),還沒詳細(xì)查看以后再補(bǔ)充

    AutowiredAnnotationBeanPostProcessor:負(fù)責(zé)依賴注入和屬性注入,比如@Autowired @Value的相應(yīng)動(dòng)作

    CommonAnnotationBeanPostProcessor:負(fù)責(zé)JSR250相關(guān)注解的解析與執(zhí)行,比如@PostContruct @Resource等

注冊(cè)配置類

    使用AnnotatedBeanDefinitionReader.register(ImportResourceAppConfig.class)將ImportResourceAppConfig的BeanDefinition注冊(cè)到beanDefinitionMaps當(dāng)中。完成這個(gè)動(dòng)作之后Spring才能拿到配置類做下一步的包掃描、依賴注入等操作

解析配置類上的注解,并完成BeanDefinition注冊(cè)

   主要就是ConfigurationClassPostProcessor和AutowiredAnnotationBeanPostProcessor兩個(gè)類啟核心作用(當(dāng)然還有這兩個(gè)牽扯出來的其他類),比如ConfigurationClassPostProcessor.ConfigurationClassPaser就是負(fù)責(zé)完成包掃描的,包含了@ComponentScan @Component @Import @ImportResource @Bean 注解的解析完成所有的BeanDefinition的創(chuàng)建并注冊(cè)到beanDefinitionMaps當(dāng)中

根據(jù)BeanDefinition實(shí)例化Spring Bean

    上一步已經(jīng)將所有的BeanDefinition準(zhǔn)備好,接下來就是遍歷他們,使用動(dòng)態(tài)代理完成對(duì)象的實(shí)例化,并最終得到Spring Bean(可能是裸對(duì)象,也可能是代理對(duì)象)。

總結(jié):簡(jiǎn)單的說Spring并不是直接根據(jù)Class文件創(chuàng)建一個(gè)Bean,而是生成對(duì)應(yīng)的BeanDefinition對(duì)象,再根據(jù)它創(chuàng)建想要的Bean,在這個(gè)過程當(dāng)中Spring提供了豐富的擴(kuò)展點(diǎn)去干預(yù)BeanDefinition狀態(tài)和Bean的狀態(tài),這些擴(kuò)展點(diǎn)就是Spring真正強(qiáng)大的原因。

到此,相信大家對(duì)“如何構(gòu)建Spring源碼運(yùn)行環(huán)境”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI