您好,登錄后才能下訂單哦!
這篇文章主要介紹了java中Spring源碼分析的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇java中Spring源碼分析文章都會有所收獲,下面我們一起來看看吧。
/**
* spring debug
* @author huangfu
*/
public class SpringDebug {
public static void main(String[] args) {
AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(SpringDebugConfig.class);
}
}
上面這一行代碼我估計使用過Spring的人都特別熟悉,如果不熟悉,那我勸你先學會使用,再去深究一些源碼的底層邏輯!
下面我們看一下,他究竟是如何一步一步的實例化bean,接管bean,然后執行各種生命周期類的!我們先不妨猜測一下,spring再讀取這些bean的時候,關于bean的信息一定是存放在了某一個實體上,那么這個實體是什么呢?這個類就是BeanDefinition
那么他存儲了什么東西呢?我們看一下它的子類AbstractBeanDefinition
里面定義這類似與這樣的屬性值,當然作者做截取了少數屬性,它里面的屬性遠遠比這多得多,它的目的就是bean實例化的時候,需要的數據不需要再通過自己去反射獲取,而是再Spring初始化的時候全部讀取,需要的時候從這里面拿就行,了解了bd的概念之后,我們是否疑惑?他讀取之后存放在哪里呢?答案是存放再beanFactory里面,所以Spring初始化的時候肯定會先實現一個bean工廠!進入到AnnotationConfigApplicationContext
里面,你會發下并沒有初始化,在那初始化呢?眾所周知,一個類再初始化的時候會先加載父類的構造函數,所以我們需要去看一下它的父類GenericApplicationContext
:
public GenericApplicationContext() {
//初始化bean的工廠
this.beanFactory = new DefaultListableBeanFactory();
}
果然不出我所料,它再父類里面創建了bean工廠,工廠有了,我們繼續回到AnnotationConfigApplicationContext
里面往下看:發現它調用了一個this(),說明它調用了自己的空構造方法,所以,我們進入看一下:
public AnnotationConfigApplicationContext() {
//初始化讀取器
this.reader = new AnnotatedBeanDefinitionReader(this);
//初始化掃描器
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
「至此我們就可以看對照上面那幅圖:初始化的時候bean工廠有了」
「然后再自己的空構造方法里面有初始化了讀取器!」
那我們繼續回到AnnotationConfigApplicationContext
構造方法里面:
/**
* 創建一個新的AnnotationConfigApplicationContext,從給定的帶注釋的類派生bean定義
* 并自動刷新上下文。
* @param annotatedClasses one or more annotated classes,
* e.g. {@link Configuration @Configuration} classes
*/
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
//讀取Spring內置的幾個的class文件轉換為bd 然后初始化bean工廠
this();
//這一步就是將配置類Config進行了注冊并解析bd
register(annotatedClasses);
//這一步是核心,Spring的理解全在這一步,這一步理解了也就可以說將Spring理解了70%
//內部做一系列的操作如調用bean工廠的后置處理器 實例化類 調用 后置處理器的前置處理 初始化類 調用后置處理器的后置處理 注冊事件監聽等操作
//完成一個類從class文件變為bean的生命周期
refresh();
}
下一步是調用register
方法,干什么呢?試想一下,有時候我們的自動掃描配置是通過注解@ComponentScan("com.service")
來配置的,這個類一般在哪?對了,一般實在配置類中的!
@Configuration
@ComponentScan("com.service")
public class SpringDebugConfig {}
為了能夠知道,我們要掃描那些包下的類,我們就必須先去解析配置類的BeanDefinition
,這樣才能獲取后續咱們要解析的包,當然這個方法不光解析了掃描的包,還解析了其他東西,本文不做講解!
好了,再往下走我們就知道了我們即將要掃描那些包下的類,讓他變成bean,那么我們繼續向下走,走到refresh();
這個方法不得了他是整個Springbean初始化的核心方法,了解了它也就能夠了解Spring的實例化,回調等一些列的問題,我們進去看看:
進來之后,我們一個方法一個方法的分析做了什么功能,首先是:
?這里是做刷新bean工廠前的一系列賦值操作,主要是為前面創建的Spring工廠很多的屬性都是空的,這個方式是為他做一些列的初始化值的操作!
?
?告訴子類刷新內部bean工廠 檢測bean工廠是否存在 判斷當前的bean工廠是否只刷新過一次,多次報錯,返回當前使用的bean工廠,當該步驟為xml時 會新建一個新的工廠并返回
?
?這里是初始化Spring的bean容器,向beanFactory內部注冊一些自己本身內置的Bean后置處理器也就是通常說的BeanPostProcessor,這個方法其實也是再初始化工廠!
?
?允許在上下文子類中對bean工廠進行后處理,作用是在BeanFactory準備工作完成后做一些定制化的處理! 但是注意,你點進去是空方法,空方法以為著什么?意味著Spring的開發者希望調用者自定義擴展時使用!
?
?其實相信看名字,大部分讀者都能夠猜出,他的目的是掃描非配置類的bd注冊到工廠里面,掃描完成之后,開始執行所有的
?BeanFactoryPostProcessors
,這里出現了第一個擴展點,自定義實現BeanFactoryPostProcessors
的時候,他的回調時機是在Spring讀取了全部的BeanDefinition
之后調用的,具體的使用方法讀者自行百度!
?這里是注冊bean的后置處理器 也就是 beanPostProcessor 的實現 還有自己內置的處理器 注意這里并沒有調用該處理器,只是將胡處理器注冊進來bean工廠! 不知道大家使用過
?beanPostProcessor
接口這個擴展點嗎?他就是再這個方法里面被注冊到Spring工廠里面的,當然注意一下,他只是注冊進去了,并沒有執行!記住并沒有執行!
?怎么說呢,這個方法作者并不準備深究,因為他和本篇文章的意圖相違背,他的目的是做一個國際化操作也就是 i18n的資源初始化
?
?Spring為我們提供了對于事件編程的封裝,一般來說事件分為三個角色,
?事件廣播器
(發布事件),事件監聽器
(監聽事件),事件源
(具體的事件信息)三個角色,這個方法的目的就是初始化事件的廣播器!
?這里又是一個擴展點,內部的方法為空,Spring并沒有實現它,供調用者實現!
?
?注冊Spring的事件監聽器,上面已經說過了,這里是初始化并且注冊事件監聽器
?
?這個方法是一個重點,他是為了實例化所有剩余的(非延遲初始化)單例。我們所說的bean的實例化,注入,解決循環依賴,回調
?beanPostProcessor
等操作都是再這里實現的!
?最后一步:發布相應的事件。Spring內置的事件
?
關于“java中Spring源碼分析”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“java中Spring源碼分析”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。