java中Spring源碼分析

這篇文章主要介紹了java中Spring源碼分析的相關(guān)知識(shí),內(nèi)容詳細(xì)易懂,操作簡單快捷,具有一定借鑒價(jià)值,相信大家閱讀完這篇java中Spring源碼分析文章都會(huì)有所收獲,下面我們一起來看看吧。

成都創(chuàng)新互聯(lián)專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作、七里河網(wǎng)絡(luò)推廣、小程序開發(fā)、七里河網(wǎng)絡(luò)營銷、七里河企業(yè)策劃、七里河品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營等,從售前售中售后,我們都將竭誠為您服務(wù),您的肯定,是我們最大的嘉獎(jiǎng);成都創(chuàng)新互聯(lián)為所有大學(xué)生創(chuàng)業(yè)者提供七里河建站搭建服務(wù),24小時(shí)服務(wù)熱線:18980820575,官方網(wǎng)址:bm7419.com

源碼分析

1.前期準(zhǔn)備

/**
* spring debug
* @author huangfu
*/
public class SpringDebug {
public static void main(String[] args) {
AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(SpringDebugConfig.class);
}
}
     

上面這一行代碼我估計(jì)使用過Spring的人都特別熟悉,如果不熟悉,那我勸你先學(xué)會(huì)使用,再去深究一些源碼的底層邏輯!

下面我們看一下,他究竟是如何一步一步的實(shí)例化bean,接管bean,然后執(zhí)行各種生命周期類的!我們先不妨猜測一下,spring再讀取這些bean的時(shí)候,關(guān)于bean的信息一定是存放在了某一個(gè)實(shí)體上,那么這個(gè)實(shí)體是什么呢?這個(gè)類就是BeanDefinition那么他存儲(chǔ)了什么東西呢?我們看一下它的子類AbstractBeanDefinition

java中Spring源碼分析        

里面定義這類似與這樣的屬性值,當(dāng)然作者做截取了少數(shù)屬性,它里面的屬性遠(yuǎn)遠(yuǎn)比這多得多,它的目的就是bean實(shí)例化的時(shí)候,需要的數(shù)據(jù)不需要再通過自己去反射獲取,而是再Spring初始化的時(shí)候全部讀取,需要的時(shí)候從這里面拿就行,了解了bd的概念之后,我們是否疑惑?他讀取之后存放在哪里呢?答案是存放再beanFactory里面,所以Spring初始化的時(shí)候肯定會(huì)先實(shí)現(xiàn)一個(gè)bean工廠!進(jìn)入到AnnotationConfigApplicationContext里面,你會(huì)發(fā)下并沒有初始化,在那初始化呢?眾所周知,一個(gè)類再初始化的時(shí)候會(huì)先加載父類的構(gòu)造函數(shù),所以我們需要去看一下它的父類GenericApplicationContext:

public GenericApplicationContext() {
   //初始化bean的工廠
   this.beanFactory = new DefaultListableBeanFactory();
}
     

果然不出我所料,它再父類里面創(chuàng)建了bean工廠,工廠有了,我們繼續(xù)回到AnnotationConfigApplicationContext里面往下看:發(fā)現(xiàn)它調(diào)用了一個(gè)this(),說明它調(diào)用了自己的空構(gòu)造方法,所以,我們進(jìn)入看一下:

public AnnotationConfigApplicationContext() {
   //初始化讀取器
   this.reader = new AnnotatedBeanDefinitionReader(this);
   //初始化掃描器
   this.scanner = new ClassPathBeanDefinitionScanner(this);
}
   

「至此我們就可以看對照上面那幅圖:初始化的時(shí)候bean工廠有了」

java中Spring源碼分析        

「然后再自己的空構(gòu)造方法里面有初始化了讀取器!」

java中Spring源碼分析        

那我們繼續(xù)回到AnnotationConfigApplicationContext構(gòu)造方法里面:

   /**
* 創(chuàng)建一個(gè)新的AnnotationConfigApplicationContext,從給定的帶注釋的類派生bean定義
* 并自動(dòng)刷新上下文。
* @param annotatedClasses one or more annotated classes,
* e.g. {@link Configuration @Configuration} classes
*/
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
//讀取Spring內(nèi)置的幾個(gè)的class文件轉(zhuǎn)換為bd  然后初始化bean工廠
this();
//這一步就是將配置類Config進(jìn)行了注冊并解析bd
register(annotatedClasses);
//這一步是核心,Spring的理解全在這一步,這一步理解了也就可以說將Spring理解了70%
//內(nèi)部做一系列的操作如調(diào)用bean工廠的后置處理器   實(shí)例化類  調(diào)用 后置處理器的前置處理   初始化類  調(diào)用后置處理器的后置處理 注冊事件監(jiān)聽等操作
//完成一個(gè)類從class文件變?yōu)閎ean的生命周期
refresh();
}
     

下一步是調(diào)用register方法,干什么呢?試想一下,有時(shí)候我們的自動(dòng)掃描配置是通過注解@ComponentScan("com.service")來配置的,這個(gè)類一般在哪?對了,一般實(shí)在配置類中的!

@Configuration
@ComponentScan("com.service")
public class SpringDebugConfig {}
     

為了能夠知道,我們要掃描那些包下的類,我們就必須先去解析配置類的BeanDefinition,這樣才能獲取后續(xù)咱們要解析的包,當(dāng)然這個(gè)方法不光解析了掃描的包,還解析了其他東西,本文不做講解!     

2.核心功能

好了,再往下走我們就知道了我們即將要掃描那些包下的類,讓他變成bean,那么我們繼續(xù)向下走,走到refresh();這個(gè)方法不得了他是整個(gè)Springbean初始化的核心方法,了解了它也就能夠了解Spring的實(shí)例化,回調(diào)等一些列的問題,我們進(jìn)去看看:

進(jìn)來之后,我們一個(gè)方法一個(gè)方法的分析做了什么功能,首先是:     

1). prepareRefresh();
?      

這里是做刷新bean工廠前的一系列賦值操作,主要是為前面創(chuàng)建的Spring工廠很多的屬性都是空的,這個(gè)方式是為他做一些列的初始化值的操作!

?             
2). obtainFreshBeanFactory()
?      

告訴子類刷新內(nèi)部bean工廠  檢測bean工廠是否存在 判斷當(dāng)前的bean工廠是否只刷新過一次,多次報(bào)錯(cuò),返回當(dāng)前使用的bean工廠,當(dāng)該步驟為xml時(shí) 會(huì)新建一個(gè)新的工廠并返回

?             
3). prepareBeanFactory(beanFactory);
?      

這里是初始化Spring的bean容器,向beanFactory內(nèi)部注冊一些自己本身內(nèi)置的Bean后置處理器也就是通常說的BeanPostProcessor,這個(gè)方法其實(shí)也是再初始化工廠!

?             
4). postProcessBeanFactory(beanFactory);
?      

允許在上下文子類中對bean工廠進(jìn)行后處理,作用是在BeanFactory準(zhǔn)備工作完成后做一些定制化的處理! 但是注意,你點(diǎn)進(jìn)去是空方法,空方法以為著什么?意味著Spring的開發(fā)者希望調(diào)用者自定義擴(kuò)展時(shí)使用!

?             
5). invokeBeanFactoryPostProcessors(beanFactory);
?      

其實(shí)相信看名字,大部分讀者都能夠猜出,他的目的是掃描非配置類的bd注冊到工廠里面,掃描完成之后,開始執(zhí)行所有的BeanFactoryPostProcessors,這里出現(xiàn)了第一個(gè)擴(kuò)展點(diǎn),自定義實(shí)現(xiàn)BeanFactoryPostProcessors的時(shí)候,他的回調(diào)時(shí)機(jī)是在Spring讀取了全部的BeanDefinition之后調(diào)用的,具體的使用方法讀者自行百度!

?             
6). registerBeanPostProcessors(beanFactory);
?      

這里是注冊bean的后置處理器 也就是  beanPostProcessor 的實(shí)現(xiàn) 還有自己內(nèi)置的處理器  注意這里并沒有調(diào)用該處理器,只是將胡處理器注冊進(jìn)來bean工廠! 不知道大家使用過beanPostProcessor接口這個(gè)擴(kuò)展點(diǎn)嗎?他就是再這個(gè)方法里面被注冊到Spring工廠里面的,當(dāng)然注意一下,他只是注冊進(jìn)去了,并沒有執(zhí)行!記住并沒有執(zhí)行!

?            
7). initMessageSource();
?      

怎么說呢,這個(gè)方法作者并不準(zhǔn)備深究,因?yàn)樗捅酒恼碌囊鈭D相違背,他的目的是做一個(gè)國際化操作也就是 i18n的資源初始化

?             
8).initApplicationEventMulticaster();
?      

Spring為我們提供了對于事件編程的封裝,一般來說事件分為三個(gè)角色,事件廣播器(發(fā)布事件),事件監(jiān)聽器(監(jiān)聽事件),事件源(具體的事件信息)三個(gè)角色,這個(gè)方法的目的就是初始化事件的廣播器!

?             
9). onRefresh();
?      

這里又是一個(gè)擴(kuò)展點(diǎn),內(nèi)部的方法為空,Spring并沒有實(shí)現(xiàn)它,供調(diào)用者實(shí)現(xiàn)!

?             
10). registerListeners();
?      

注冊Spring的事件監(jiān)聽器,上面已經(jīng)說過了,這里是初始化并且注冊事件監(jiān)聽器

?             
11). finishBeanFactoryInitialization(beanFactory);
?      

這個(gè)方法是一個(gè)重點(diǎn),他是為了實(shí)例化所有剩余的(非延遲初始化)單例。我們所說的bean的實(shí)例化,注入,解決循環(huán)依賴,回調(diào)beanPostProcessor等操作都是再這里實(shí)現(xiàn)的!

?        
12). finishRefresh();
?      

最后一步:發(fā)布相應(yīng)的事件。Spring內(nèi)置的事件

?        

關(guān)于“java中Spring源碼分析”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對“java中Spring源碼分析”知識(shí)都有一定的了解,大家如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

文章題目:java中Spring源碼分析
本文路徑:http://bm7419.com/article32/gihssc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信小程序、GoogleApp開發(fā)、網(wǎng)站導(dǎo)航定制網(wǎng)站、微信公眾號(hào)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

手機(jī)網(wǎng)站建設(shè)