初學者Spring IOC原始碼剖析,就是這麼簡單

一、Spring IOC概述

IOC(控制反轉),不是什麼技術的,而是給軟體設計的一種設計思想。IOC就是將原來我們在程式中透過手動new出來物件的控制權,交由IOC容器來管理。

生活例子

在現實生活中,比如人們下班後,回到家裡頭自己需要動手做飯,但是在沒有菜、米飯、鹽巴、辣椒等情況下,然而我們是

主動

去菜市場、超市購買。值得注意的是:這些都是自己

“主動”

去實現的過程。

然而到今天,由於網際網路的發展,當人們下班後回到家裡後,太累不想自己動手做飯了,但是肚子又很餓想吃飯。怎麼辦呢?第一想法就是

點外賣

,下訂單後,不到10分鐘就會有

外賣小哥

送過來了。

注意

:做飯、買菜等過程你並沒有

“主動”

去實現,而是

點外賣

這頓飯是由飯店自己完成的包括買菜呀、油呀、鹽巴等複雜的過程,但是完全達到解決自己的餓肚子的問題,甚至比你做的還好吃而且更香。

Spring IOC到底是啥?

透過上述的例子,我們再次理解

IOC(控制反轉)

的概念。

控制反轉是一種透過描述在Java中可以透過XML或註解方式,並透過第三方Spring去產生及獲取特定物件的方式。

XML:就好比上述例子透過“下訂單”,來獲取我們想要的“外賣”

註解:也和XML差不多,只是換一種方式獲取而已,比如不“下訂單”,而是透過直接“打電話”讓飯店給我送過來一份飯(備註:雞蛋+雞腿+可口可樂),也可以獲取

好處:

降低物件之間的耦合

無需知道這個類是怎麼實現的,只要我們知道它有什麼用就行,

直接伸手和Spring IOC容器拿即可。

就好比直接伸手和

配送員

拿外賣一樣,飯店提供配送員,就好比IOC提供給我們的一個

介面

一樣,想要什麼就去實現介面即可。

二、IOC容器

Spring IOC容器設計,主要是基於BeanFactory和ApplicationContexe介面,而ApplicationContext是BeanFactory子介面,ApplicationContext是在BeanFactory基礎上進行了完整其他功能。

1、BeanFactory底層

初學者Spring IOC原始碼剖析,就是這麼簡單

2、ApplicationContexe

ApplicationContext 常見實現類

1、

ClassPathXmlApplicationContext

:取classpath中的資源

2、

FileSystemXmlApplicationContext

:讀取指定路徑的資源

3、

XmlWebApplicationContext

:需要在Web的環境下才可以執行

三、啟動過程分析

第一步:從 ClassPathXmlApplicationContext 的構造方法入手,透過ClassPathXmlApplicationContext跟蹤我們會發現,它主要完成一下三個步驟:

初學者Spring IOC原始碼剖析,就是這麼簡單

初始化父類容器AbstractXmlApplicationContext

設定資原始檔路徑:setConfigLocations(configLocations)

核心方法refresh()

簡單瞭解refresh方法

初學者Spring IOC原始碼剖析,就是這麼簡單

該方法核心的兩步

1、建立BeanFactory

// 這步比較關鍵,這步完成後,配置檔案就會解析成一個個 Bean 定義,註冊到 BeanFactory 中

//當然,這裡說的 Bean 還沒有初始化,只是配置資訊都提取出來了

//註冊也只是將這些資訊都儲存到了註冊中心(說到底核心是一個 beanName-> beanDefinition 的 map)

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

2、例項化Bean

// 初始化所有的 singleton beans

//(lazy-init 的除外)

finishBeanFactoryInitialization(beanFactory);

講解建立BeanFactory

/**

* Tell the subclass to refresh the internal bean factory。

* @return the fresh BeanFactory instance

* @see #refreshBeanFactory()

* @see #getBeanFactory()

*/

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {

//核心

refreshBeanFactory();

ConfigurableListableBeanFactory beanFactory = getBeanFactory();

if (logger。isDebugEnabled()) {

logger。debug(“Bean factory for ” + getDisplayName() + “: ” + beanFactory);

}

return beanFactory;

}

透過看原始碼發現,該方法的主要兩個步驟:

重新整理BeanFactory,即refreshBeanFactory()

獲取BeanFactory,即getBeanFactory()

注:

它的核心是refreshBeanFactory()

其實在建立BeanFactory過程,BeanDefinition註冊到啦BeanFactory中的一個Co ncurrentHashMap物件中,並且以BeanName為key,BeanDefinition為value註冊。

本篇文章如有錯的地方,歡迎在評論指正。

另,如果覺得這本篇文章寫得不錯,有點東西的話,大家來個三連吧!【點贊+關注+分享】。