初學者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底層
2、ApplicationContexe
ApplicationContext 常見實現類
1、
ClassPathXmlApplicationContext
:取classpath中的資源
2、
FileSystemXmlApplicationContext
:讀取指定路徑的資源
3、
XmlWebApplicationContext
:需要在Web的環境下才可以執行
三、啟動過程分析
第一步:從 ClassPathXmlApplicationContext 的構造方法入手,透過ClassPathXmlApplicationContext跟蹤我們會發現,它主要完成一下三個步驟:
初始化父類容器AbstractXmlApplicationContext
設定資原始檔路徑:setConfigLocations(configLocations)
核心方法refresh()
簡單瞭解refresh方法
該方法核心的兩步
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註冊。
本篇文章如有錯的地方,歡迎在評論指正。
另,如果覺得這本篇文章寫得不錯,有點東西的話,大家來個三連吧!【點贊+關注+分享】。