Spring Ioc 源碼分析(一)--Spring Ioc容器的加載

1.目標(biāo):熟練使用spring,并分析其源碼,了解其中的思想胎许。這篇主要介紹spring ioc 容器的加載
2.前提條件:會(huì)使用debug
3.源碼分析方法:Intellj idea debug 模式下源碼追溯
通過(guò)ClassPathXmlApplicationContext 進(jìn)行xml 件的讀取,從每個(gè)堆棧中讀取程序的運(yùn)行信息
4.注意:由于Spring的類(lèi)繼承體系比較復(fù)雜,不能全部貼圖,所以只將分析源碼之后發(fā)現(xiàn)的最主要的類(lèi)繼承結(jié)構(gòu)類(lèi)圖貼在下方藕漱。
5.關(guān)于Spring Ioc Demo:我們從demo入手一步步進(jìn)行代碼追溯。

1.Spring Ioc Demo


1.定義數(shù)據(jù)訪問(wèn)接口IUserDao.java

public interface IUserDao {  
    public void InsertUser(String username,String password);
}

2.定義IUserDao.java實(shí)現(xiàn)類(lèi)IUserDaoImpl.java

public class UserDaoImpl implements IUserDao {    
    @Override    
    public void InsertUser(String username, String password) { 
        System.out.println("----UserDaoImpl --addUser----");    
    }
}

3.定義業(yè)務(wù)邏輯接口UserService.java

public interface UserService {    
    public void addUser(String username,String password);
}

4.定義UserService.java實(shí)現(xiàn)類(lèi)UserServiceImpl.java

public class UserServiceImpl implements UserService {    
    private     IUserDao  userDao;    //set方法  
    public void  setUserDao(IUserDao  userDao) {        
        this.userDao = userDao;   
    }    
    @Override    
    public void addUser(String username,String password) { 
        userDao.InsertUser(username,password);    
    }
}

bean.xml配置文件

<beans xmlns="http://www.springframework.org/schema/beans"  
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
   xsi:schemaLocation="http://www.springframework.org/schema/beans  
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd         ">  
 <!--id名字自己取崭闲,class表示他代表的類(lèi)肋联,如果在包里的話需要加上包名-->    
 <bean id="userService"  class="UserServiceImpl" >      
        <!--property代表是通過(guò)set方法注入,ref的值表示注入的內(nèi)容-->
        <property  name="userDao"  ref="userDao"/>  
 </bean>    
  <bean id="userDao"  class="UserDaoImpl"/>
</beans>

2.ApplicationContext 繼承結(jié)構(gòu):


1.頂層接口:ApplicationContext
2.ClassPathXmlApplicationContext實(shí)現(xiàn)類(lèi)繼承AbstractXmlApplication 抽象類(lèi)
3.AbstractXmlApplication 繼承AbstractRefreshableConfigApplicationContext
4.AbstractRefreshableConfigApplicationContext抽象類(lèi)繼承AbstractRefreshableApplicationContext
5.AbstractRefreshableApplicationContext 繼承 AbstractApplicationContext
6.AbstractApplicationContext 實(shí)現(xiàn)ConfigurableApplicationContext 接口
7.ConfigurableApplicationContext 接口繼承
ApplicationContext接口
總體來(lái)說(shuō)繼承實(shí)現(xiàn)結(jié)構(gòu)較深,內(nèi)部使用了大量適配器模式刁俭。
以ClassPathXmlApplicationContext為例橄仍,繼承類(lèi)圖如下圖所示:


Spring ioc .png

3.Spring Ioc容器加載過(guò)程源碼詳解


在開(kāi)始之前,先介紹一個(gè)整體的概念牍戚。即spring ioc容器的加載侮繁,大體上經(jīng)過(guò)以下幾個(gè)過(guò)程:
資源文件定位、解析如孝、注冊(cè)宪哩、實(shí)例化

1.資源文件定位
其中資源文件定位,一般是在ApplicationContext的實(shí)現(xiàn)類(lèi)里完成的暑竟,因?yàn)锳pplicationContext接口繼承ResourcePatternResolver 接口斋射,ResourcePatternResolver接口繼承ResourceLoader接口,ResourceLoader其中的getResource()方法但荤,可以將外部的資源罗岖,讀取為Resource類(lèi)。


2.解析DefaultBeanDefinitionDocumentReader腹躁,
解析主要是在BeanDefinitionReader中完成的桑包,最常用的實(shí)現(xiàn)類(lèi)是XmlBeanDefinitionReader,其中的loadBeanDefinitions()方法纺非,負(fù)責(zé)讀取Resource哑了,并完成后續(xù)的步驟赘方。ApplicationContext完成資源文件定位之后,是將解析工作委托給XmlBeanDefinitionReader來(lái)完成的
解析這里涉及到很多步驟弱左,最常見(jiàn)的情況窄陡,資源文件來(lái)自一個(gè)XML配置文件。首先是BeanDefinitionReader拆火,將XML文件讀取成w3c的Document文檔跳夭。
DefaultBeanDefinitionDocumentReader對(duì)Document進(jìn)行進(jìn)一步解析。然后DefaultBeanDefinitionDocumentReader又委托給BeanDefinitionParserDelegate進(jìn)行解析们镜。如果是標(biāo)準(zhǔn)的xml namespace元素币叹,會(huì)在Delegate內(nèi)部完成解析,如果是非標(biāo)準(zhǔn)的xml namespace元素模狭,則會(huì)委托合適的NamespaceHandler進(jìn)行解析最終解析的結(jié)果都封裝為BeanDefinitionHolder颈抚,至此解析就算完成。
后續(xù)會(huì)進(jìn)行細(xì)致講解嚼鹉。


3.注冊(cè)
然后bean的注冊(cè)是在BeanFactory里完成的贩汉,BeanFactory接口最常見(jiàn)的一個(gè)實(shí)現(xiàn)類(lèi)是DefaultListableBeanFactory,它實(shí)現(xiàn)了BeanDefinitionRegistry接口反砌,所以其中的registerBeanDefinition()方法雾鬼,可以對(duì)BeanDefinition進(jìn)行注冊(cè)這里附帶一提,最常見(jiàn)的XmlWebApplicationContext不是自己持有BeanDefinition的宴树,它繼承自AbstractRefreshableApplicationContext策菜,其持有一個(gè)DefaultListableBeanFactory的字段,就是用它來(lái)保存BeanDefinition
所謂的注冊(cè)酒贬,其實(shí)就是將BeanDefinition的name和實(shí)例又憨,保存到一個(gè)Map中。剛才說(shuō)到锭吨,最常用的實(shí)現(xiàn)DefaultListableBeanFactory蠢莺,其中的字段就是beanDefinitionMap,是一個(gè)ConcurrentHashMap零如。
代碼如下:
>1.DefaultListableBeanFactory繼承實(shí)現(xiàn)關(guān)系

public class DefaultListableBeanFactory
extends 
AbstractAutowireCapableBeanFactory   
implements
ConfigurableListableBeanFactory, 
BeanDefinitionRegistry,
Serializable { 
     // DefaultListableBeanFactory的實(shí)例中最終保存了所有注冊(cè)的bean    beanDefinitionMap
     /** Map of bean definition objects, keyed by bean name */
     private final Map<String, BeanDefinition> beanDefinitionMap 
     = new ConcurrentHashMap<String, BeanDefinition>(64); 
     //實(shí)現(xiàn)BeanDefinitionRegistry中定義的registerBeanDefinition()抽象方法
     public void registerBeanDefinition(String beanName, BeanDefinition    beanDefinition)      throws BeanDefinitionStoreException {
     }

>2.BeanDefinitionRegistry接口

public interface BeanDefinitionRegistry extends AliasRegistry {   
    //定義注冊(cè)BeanDefinition實(shí)例的抽象方法
    void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)         throws BeanDefinitionStoreException;

4.實(shí)例化


注冊(cè)也完成之后躏将,在BeanFactory的getBean()方法之中,會(huì)完成初始化考蕾,也就是依賴注入的過(guò)程
大體上的流程就是這樣祸憋,下一篇博客,再具體地從代碼層面進(jìn)行介紹肖卧。

博客搬家:大坤的個(gè)人博客
歡迎評(píng)論哦~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蚯窥,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌拦赠,老刑警劉巖巍沙,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件清焕,死亡現(xiàn)場(chǎng)離奇詭異竿报,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)愉豺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)允乐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)务甥,“玉大人,你說(shuō)我怎么就攤上這事喳篇。” “怎么了态辛?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵麸澜,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我奏黑,道長(zhǎng)炊邦,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任熟史,我火速辦了婚禮馁害,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蹂匹。我一直安慰自己碘菜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布限寞。 她就那樣靜靜地躺著忍啸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪履植。 梳的紋絲不亂的頭發(fā)上计雌,一...
    開(kāi)封第一講書(shū)人閱讀 49,144評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音玫霎,去河邊找鬼凿滤。 笑死,一個(gè)胖子當(dāng)著我的面吹牛庶近,可吹牛的內(nèi)容都是我干的翁脆。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼拦盹,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼鹃祖!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤恬口,失蹤者是張志新(化名)和其女友劉穎校读,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體祖能,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡歉秫,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了养铸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片雁芙。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖钞螟,靈堂內(nèi)的尸體忽然破棺而出兔甘,到底是詐尸還是另有隱情,我是刑警寧澤鳞滨,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布洞焙,位于F島的核電站,受9級(jí)特大地震影響拯啦,放射性物質(zhì)發(fā)生泄漏澡匪。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一褒链、第九天 我趴在偏房一處隱蔽的房頂上張望唁情。 院中可真熱鬧,春花似錦甫匹、人聲如沸甸鸟。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)哀墓。三九已至,卻和暖如春喷兼,著一層夾襖步出監(jiān)牢的瞬間篮绰,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工季惯, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留吠各,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓勉抓,卻偏偏與公主長(zhǎng)得像贾漏,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子藕筋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容