首頁  >  文章  >  Java  >  java中Spring源碼分析

java中Spring源碼分析

WBOY
WBOY轉載
2023-04-30 23:13:05812瀏覽

原始碼分析

1.前期準備

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

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

下面我們來看看,他究竟是如何一步一步的實例化bean,接管bean,然後執行各種生命週期類別的!我們先不妨猜測一下,spring再讀取這些bean的時候,關於bean的資訊一定是存放在了某一個實體上,那麼這個實體是什麼呢?這個類別就是BeanDefinition那他儲存了什麼東西呢?我們來看看它的子類別AbstractBeanDefinition

java中Spring源碼分析        

#裡面定義這類似與這樣的屬性值,當然作者做截斷了少數屬性,它裡面的屬性遠遠比這多得多,它的目的就是bean實例化的時候,需要的資料不需要再透過自己去反射獲取,而是再Spring初始化的時候全部讀取,需要的時候從這裡面拿就行,了解了bd的概念之後,我們是否疑惑?他讀取之後存放在哪裡呢?答案是存放再beanFactory裡面,所以Spring初始化的時候一定會先實現一個bean工廠!進入AnnotationConfigApplicationContext裡面,你會發下來並沒有初始化,在那初始化呢?眾所周知,一個類別再初始化的時候會先載入父類別的建構函數,所以我們需要去看一下它的父類別GenericApplicationContext:

<code>public GenericApplicationContext() {<br>    //初始化bean的工厂<br>    this.beanFactory = new DefaultListableBeanFactory();<br>}</code>     

果然不出我所料,它再父類別裡面創建了bean工廠,工廠有了,我們繼續回到AnnotationConfigApplicationContext裡面往下看:發現它調用了一個this(),說明它調用了自己的空構造方法,所以,我們進入看一下:

<code>public AnnotationConfigApplicationContext() {<br>    //初始化读取器<br>    this.reader = new AnnotatedBeanDefinitionReader(this);<br>    //初始化扫描器<br>    this.scanner = new ClassPathBeanDefinitionScanner(this);<br>}</code>   

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

##        java中Spring源碼分析

#「然後再自己的空構造方法裡面有初始化了讀取器!」

        java中Spring源碼分析
那我們繼續回到

AnnotationConfigApplicationContext 建構方法裡面:

<code>   /**<br>	 * 创建一个新的AnnotationConfigApplicationContext,从给定的带注释的类派生bean定义<br>	 * 并自动刷新上下文。<br>	 * @param annotatedClasses one or more annotated classes,<br>	 * e.g. {@link Configuration @Configuration} classes<br>	 */<br>public AnnotationConfigApplicationContext(Class>... annotatedClasses) {<br>//读取Spring内置的几个的class文件转换为bd  然后初始化bean工厂<br>this();<br>//这一步就是将配置类Config进行了注册并解析bd<br>		register(annotatedClasses);<br>//这一步是核心,Spring的理解全在这一步,这一步理解了也就可以说将Spring理解了70%<br>//内部做一系列的操作如调用bean工厂的后置处理器   实例化类  调用 后置处理器的前置处理   初始化类  调用后置处理器的后置处理 注册事件监听等操作<br>//完成一个类从class文件变为bean的生命周期<br>		refresh();<br>	}</code>     
下一步就是呼叫

register方法,幹嘛呢?試想一下,有時候我們的自動掃描配置是透過註解@ComponentScan("com.service")來設定的,這個類別一般在哪?對了,一般實在配置類別的!

<code>@Configuration<br>@ComponentScan("com.service")<br>public class SpringDebugConfig {}</code>     
為了能夠知道,我們要掃描那些包下的類,我們就必須先去解析配置類的

BeanDefinition,這樣才能獲取後續咱們要解析的包,當然這個方法不光解析了掃描的包,還解析了其他東西,本文不做講解!

2.核心功能

好了,再往下走我們就知道了我們即將要掃描那些包下的類,讓他變成bean,那麼我們繼續向下走,走到

refresh();這個方法不得了他是整個Springbean初始化的核心方法,了解了它也就能夠了解Spring的實例化,回調等一些列的問題,我們進去看看:

進來之後,我們一個方法一個方法的分析做了什麼功能,首先是:     

1). prepareRefresh();
❝      
這裡是做刷新bean工廠前的一系列賦值操作,主要是為前面創建的Spring工廠很多的屬性都是空的,這個方式是為他做一些列的初始化值的操作!

❞             

2 ). obtainFreshBeanFactory()
❝      
告訴子類別刷新內部bean工廠 檢測bean工廠是否存在判斷當前的bean工廠是否只刷新過一次,多次報錯,返回當前使用的bean工廠,當步驟為xml時會新建一個新的工廠並返回

❞             

3). prepareBeanFactory(beanFactory);
❝      # beanFactory內部註冊一些自己本身內建的Bean後置處理器也就是通常說的BeanPostProcessor,這個方法其實也是再初始化工廠!
❞             
4). postProcessBeanFactory(beanFactory);
❝      

允許在情境子類別中對bean進行後處理,準備完成工作後準備完成工作的處理! 但要注意,你點進去是空方法,空方法以為什麼?意味著Spring的開發者希望呼叫者自訂擴充時使用!

❞             
#5). invokeBeanFactoryPostProcessors(beanFactory);
#❝      

其實有掃描名字,讀者大多能猜出非配置bd註冊到工廠裡面,掃描完成之後,開始執行所有的BeanFactoryPostProcessors,這裡出現了第一個擴展點,自定義實現BeanFactoryPostProcessors的時候,他的回調時機是在Spring讀取了全部的BeanDefinition之後呼叫的,具體的使用方法讀者自行百度!

❞             
#6). registerBeanPostProcessors(beanFactory);
❝      

這裡是註冊bean的後置處理器與裝置為原始碼這裡並沒有呼叫該處理器,只是將胡處理器註冊進來bean工廠! 不知道大家使用過beanPostProcessor接口這個擴充點嗎?他就是再這個方法裡面被註冊到Spring工廠裡面的,當然注意一下,他只是註冊進去了,並沒有執行!記住並沒有執行!

❞            
7). initMessageSource();
❝      

怎麼說呢,這個方法作者並不准備深究,因為他和本篇文章的意圖相違背,他的目的是要做一個國際化作業也就是i18n的資源初始化

❞             
8).initApplicationEventMulticaster();
❝的封裝,一般來說事件分為三個角色,

事件廣播器(發布事件),事件監聽器(監聽事件),事件來源(具體的事件資訊)三個角色,這個方法的目的就是初始化事件的廣播器! ❞             

9). onRefresh();
❝      

9).這裡又是一個擴充點,內部的方法,以供呼叫!

❞             
10). registerListeners();
❝      

註冊Spring的事件監聽器,上面已經說過了,這裡是初始化並且註冊事件監聽器

❞             
11). finishBeanFactoryInitialization(beanFactory);
#❝      

這個方法是重點,祂是為了實例化所有剩餘的(非延遲實例化所有剩餘的(非延遲實例化)單例。我們所說的bean的實例化,注入,解決循環依賴,回呼beanPostProcessor等操作都是再這裡實現的!

❞        
12). finishRefresh();
❝      

最後一步:發佈對應的事件。 Spring內建的事件

❞        
#

以上是java中Spring源碼分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除