兩種實現(xiàn): 依賴查找(DL)和依賴注入(DI)。
在臺兒等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供成都網(wǎng)站設(shè)計、做網(wǎng)站 網(wǎng)站設(shè)計制作按需網(wǎng)站制作,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),成都品牌網(wǎng)站建設(shè),網(wǎng)絡(luò)營銷推廣,成都外貿(mào)網(wǎng)站建設(shè),臺兒網(wǎng)站建設(shè)費用合理。IOC 和 DI 、DL 的關(guān)系(這個 DL,Avalon 和 EJB 就是使用的這種方式實現(xiàn)的 IoC):
DL 已經(jīng)被拋棄,因為他需要用戶自己去是使用 API 進(jìn)行查找資源和組裝對象。即有侵入性。
注意:Java 使用 DI 方式實現(xiàn) IoC 的不止 Spring,包括 Google 的 Guice,還有一個冷門的 PicoContainer(極度輕量,但只提供 IoC)。
Spring 的 IoC 設(shè)計支持以下功能:
其中,最重要的就是依賴注入,從 XML 的配置上說, 即 ref 標(biāo)簽。對應(yīng) Spring RuntimeBeanReference 對象。
對于 IoC 來說,最重要的就是容器。容器管理著 Bean 的生命周期,控制著 Bean 的依賴注入。
那么, Spring 如何設(shè)計容器的呢?
Spring 作者 Rod Johnson 設(shè)計了兩個接口用以表示容器。
BeanFactory 粗暴簡單,可以理解為就是個 HashMap,Key 是 BeanName,Value 是 Bean 實例。通常只提供注冊(put),獲?。╣et)這兩個功能。我們可以稱之為 “低級容器”。
ApplicationContext 可以稱之為 “高級容器”。因為他比 BeanFactory 多了更多的功能。他繼承了多個接口。因此具備了更多的功能。
例如資源的獲取,支持多種消息(例如 JSP tag 的支持),對 BeanFactory 多了工具級別的支持等待。所以你看他的名字,已經(jīng)不是 BeanFactory 之類的工廠了,而是 “應(yīng)用上下文”, 代表著整個大容器的所有功能。
該接口定義了一個 refresh 方法,此方法是所有閱讀 Spring 源碼的人的最熟悉的方法,用于刷新整個容器,即重新加載/刷新所有的 bean。
當(dāng)然,除了這兩個大接口,還有其他的輔助接口,但我今天不會花太多篇幅介紹他們。
為了更直觀的展示 “低級容器” 和 “高級容器” 的關(guān)系,我這里通過常用的 ClassPathXmlApplicationContext 類,來展示整個容器的層級 UML 關(guān)系。
有點復(fù)雜? 先不要慌,我來解釋一下。
最上面的 BeanFactory 知道吧?我就不講了。
下面的 3 個綠色的,都是功能擴展接口,這里就不展開講。
看下面的隸屬 ApplicationContext 粉紅色的 “高級容器”,依賴著 “低級容器”,這里說的是依賴,不是繼承哦。他依賴著 “低級容器” 的 getBean 功能。而高級容器有更多的功能:支持不同的信息源頭,可以訪問文件資源,支持應(yīng)用事件(Observer 模式)。
通常用戶看到的就是 “高級容器”。 但 BeanFactory 也非常夠用啦!
左邊灰色區(qū)域的是 “低級容器”, 只負(fù)責(zé)加載 Bean,獲取 Bean。容器其他的高級功能是沒有的。例如上圖畫的 refresh 刷新 Bean 工廠所有配置。生命周期事件回調(diào)等。
好,解釋了低級容器和高級容器,我們可以看看一個 IoC 啟動過程是什么樣子的。說白了,就是 ClassPathXmlApplicationContext 這個類,在啟動時,都做了啥。(由于我這是 interface21 的代碼,肯定和你的 Spring 4.x 系列不同)。
下圖是 ClassPathXmlApplicationContext 的構(gòu)造過程,實際就是 Spring IoC 的初始化過程。
注意,這里為了理解方便,有所簡化。
這里再用文字來描述這個過程:
用戶構(gòu)造 ClassPathXmlApplicationContext(簡稱 CPAC)
CPAC 首先訪問了 “抽象高級容器” 的 final 的 refresh 方法,這個方法是模板方法。所以要回調(diào)子類(低級容器)的 refreshBeanFactory 方法,這個方法的作用是使用低級容器加載所有 BeanDefinition 和 Properties 到容器中。
簡單說就是:
低級容器 加載配置文件(從 XML,數(shù)據(jù)庫,Applet),并解析成 BeanDefinition 到低級容器中。
所以,一定要把 “低級容器” 和“高級容器” 的區(qū)別弄清楚。不能一葉障目不見泰山。
好,當(dāng)我們創(chuàng)建好容器,就會使用 getBean 方法,獲取 Bean,而 getBean 的流程如下:
從圖中可以看出,getBean 的操作都是在低級容器里操作的。其中有個遞歸操作,這個是什么意思呢?
假設(shè):當(dāng) Bean_A 依賴著 Bean_B,而這個 Bean_A 在加載的時候,其配置的 ref = “Bean_B” 在解析的時候只是一個占位符,被放入了 Bean_A 的屬性集合中,當(dāng)調(diào)用 getBean 時,需要真正 Bean_B 注入到 Bean_A 內(nèi)部時,就需要從容器中獲取這個 Bean_B,因此產(chǎn)生了遞歸。
為什么不是在加載的時候,就直接注入呢?因為加載的順序不同,很可能 Bean_A 依賴的 Bean_B 還沒有加載好,也就無法從容器中獲取,你不能要求用戶把 Bean 的加載順序排列好,這是不人道的。
所以,Spring 將其分為了 2 個步驟:
加載所有的 Bean 配置成 BeanDefinition 到容器中,如果 Bean 有依賴關(guān)系,則使用占位符暫時代替。
所以 ApplicationContext refresh 方法里面的操作不只是 IoC,是高級容器的所有功能(包括 IoC),IoC 的功能在低級容器里就可以實現(xiàn)。
說了這么多,不知道你有沒有理解Spring IoC? 這里小結(jié)一下:IoC 在 Spring 里,只需要低級容器就可以實現(xiàn),2 個步驟:
加載配置文件,解析成 BeanDefinition 放在 Map 里。
上面就是 Spring 低級容器(BeanFactory)的 IoC。
至于高級容器 ApplicationContext,他包含了低級容器的功能,當(dāng)他執(zhí)行 refresh 模板方法的時候,將刷新整個容器的 Bean。同時其作為高級容器,包含了太多的功能。一句話,他不僅僅是 IoC。他支持不同信息源頭,支持 BeanFactory 工具類,支持層級容器,支持訪問文件資源,支持事件發(fā)布通知,支持接口回調(diào)等等。
可以預(yù)見,隨著 Spring 的不斷發(fā)展,高級容器的功能會越來越多。
誠然,了解 IoC 的過程,實際上為了了解 Spring 初始化時,各個接口的回調(diào)時機。例如 InitializingBean,BeanFactoryAware,ApplicationListener 等等接口,這些接口的作用,筆者之前寫過一篇文章進(jìn)行介紹,有興趣可以看一下,關(guān)鍵字:Spring 必知必會 擴展接口。
但是請注意,實現(xiàn) Spring 接口代表著你這個應(yīng)用就綁定死 Spring 了!代表 Spring 具有侵入性!要知道,Spring 發(fā)布時,無侵入性就是他大的宣傳點之一 —— 即 IoC 容器可以隨便更換,代碼無需變動。而現(xiàn)如今,Spring 已然成為 J2EE 社區(qū)準(zhǔn)官方解決方案,也沒有了所謂的侵入性這個說法。因為他就是標(biāo)準(zhǔn),和 Servlet 一樣,你能不實現(xiàn) Servlet 的接口嗎?: -)
創(chuàng)新互聯(lián)www.cdcxhl.cn,專業(yè)提供香港、美國云服務(wù)器,動態(tài)BGP最優(yōu)骨干路由自動選擇,持續(xù)穩(wěn)定高效的網(wǎng)絡(luò)助力業(yè)務(wù)部署。公司持有工信部辦法的idc、isp許可證, 機房獨有T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確進(jìn)行流量調(diào)度,確保服務(wù)器高可用性。佳節(jié)活動現(xiàn)已開啟,新人活動云服務(wù)器買多久送多久。
文章題目:一文解析SpringIOC面試中常問的那些核心題!-創(chuàng)新互聯(lián)
URL分享:http://www.rwnh.cn/article24/jdjce.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供域名注冊、品牌網(wǎng)站建設(shè)、網(wǎng)站排名、品牌網(wǎng)站設(shè)計、定制網(wǎng)站、網(wǎng)站設(shè)計
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)