成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

面試被問爛的 Spring IOC(求求你別再問了)

denson / 563人閱讀

摘要:例如資源的獲取,支持多種消息例如的支持,對多了工具級(jí)別的支持等待。最上面的知道吧我就不講了。生命周期事件回調(diào)等。他支持不同信息源頭,支持工具類,支持層級(jí)容器,支持訪問文件資源,支持事件發(fā)布通知,支持接口回調(diào)等等。

廣義的 IOC

IoC(Inversion of Control) 控制反轉(zhuǎn),即“不用打電話過來,我們會(huì)打給你”。 兩種實(shí)現(xiàn):
依賴查找(DL)和依賴注入(DI)。

IOC 和 DI 、DL 的關(guān)系(這個(gè) DL,Avalon 和 EJB 就是使用的這種方式實(shí)現(xiàn)的 IoC):

DL 已經(jīng)被拋棄,因?yàn)樗枰脩糇约喝ナ鞘褂?API 進(jìn)行查找資源和組裝對象。即有侵入性。

DI 是 Spring使用的方式,容器負(fù)責(zé)組件的裝配。

注意:Java 使用 DI 方式實(shí)現(xiàn) IoC 的不止 Spring,包括 Google 的 Guice,還有一個(gè)冷門的 PicoContainer(極度輕量,但只提供 IoC)。

Spring 的 IoC

Spring 的 IoC 設(shè)計(jì)支持以下功能:

依賴注入

依賴檢查

自動(dòng)裝配

支持集合

指定初始化方法和銷毀方法

支持回調(diào)某些方法(但是需要實(shí)現(xiàn) Spring 接口,略有侵入)

其中,最重要的就是依賴注入,從 XML 的配置上說, 即 ref 標(biāo)簽。對應(yīng) Spring RuntimeBeanReference 對象。

對于 IoC 來說,最重要的就是容器。容器管理著 Bean 的生命周期,控制著 Bean 的依賴注入。

那么, Spring 如何設(shè)計(jì)容器的呢?

Spring 作者 Rod Johnson 設(shè)計(jì)了兩個(gè)接口用以表示容器。

BeanFactory

ApplicationContext

BeanFactory 粗暴簡單,可以理解為就是個(gè) HashMap,Key 是 BeanName,Value 是 Bean 實(shí)例。通常只提供注冊(put),獲?。╣et)這兩個(gè)功能。我們可以稱之為 “低級(jí)容器”。

ApplicationContext 可以稱之為 “高級(jí)容器”。因?yàn)樗?BeanFactory 多了更多的功能。他繼承了多個(gè)接口。因此具備了更多的功能。例如資源的獲取,支持多種消息(例如 JSP tag 的支持),對 BeanFactory 多了工具級(jí)別的支持等待。所以你看他的名字,已經(jīng)不是 BeanFactory 之類的工廠了,而是 “應(yīng)用上下文”, 代表著整個(gè)大容器的所有功能。該接口定義了一個(gè) refresh 方法,此方法是所有閱讀 Spring 源碼的人的最熟悉的方法,用于刷新整個(gè)容器,即重新加載/刷新所有的 bean。

當(dāng)然,除了這兩個(gè)大接口,還有其他的輔助接口,但我今天不會(huì)花太多篇幅介紹他們。

為了更直觀的展示 “低級(jí)容器” 和 “高級(jí)容器” 的關(guān)系,我這里通過常用的 ClassPathXmlApplicationContext 類,來展示整個(gè)容器的層級(jí) UML 關(guān)系。

有點(diǎn)復(fù)雜? 先不要慌,我來解釋一下。

最上面的 BeanFactory 知道吧?我就不講了。

下面的 3 個(gè)綠色的,都是功能擴(kuò)展接口,這里就不展開講。

看下面的隸屬 ApplicationContext 粉紅色的 “高級(jí)容器”,依賴著 “低級(jí)容器”,這里說的是依賴,不是繼承哦。他依賴著 “低級(jí)容器” 的 getBean 功能。而高級(jí)容器有更多的功能:支持不同的信息源頭,可以訪問文件資源,支持應(yīng)用事件(Observer 模式)。

通常用戶看到的就是 “高級(jí)容器”。 但 BeanFactory 也非常夠用啦!

左邊灰色區(qū)域的是 “低級(jí)容器”, 只負(fù)載加載 Bean,獲取 Bean。容器其他的高級(jí)功能是沒有的。例如上圖畫的 refresh 刷新 Bean 工廠所有配置。生命周期事件回調(diào)等。

好,解釋了低級(jí)容器和高級(jí)容器,我們可以看看一個(gè) IoC 啟動(dòng)過程是什么樣子的。說白了,就是 ClassPathXmlApplicationContext 這個(gè)類,在啟動(dòng)時(shí),都做了啥。(由于我這是 interface21 的代碼,肯定和你的 Spring 4.x 系列不同)。

下圖是 ClassPathXmlApplicationContext 的構(gòu)造過程,實(shí)際就是 Spring IoC 的初始化過程。

注意,這里為了理解方便,有所簡化。

這里再用文字來描述這個(gè)過程:

用戶構(gòu)造 ClassPathXmlApplicationContext(簡稱 CPAC)

CPAC 首先訪問了 “抽象高級(jí)容器” 的 final 的 refresh 方法,這個(gè)方法是模板方法。所以要回調(diào)子類(低級(jí)容器)的
refreshBeanFactory 方法,這個(gè)方法的作用是使用低級(jí)容器加載所有 BeanDefinition 和 Properties
到容器中。

低級(jí)容器加載成功后,高級(jí)容器開始處理一些回調(diào),例如 Bean 后置處理器?;卣{(diào) setBeanFactory
方法?;蛘咦员O(jiān)聽器等,發(fā)布事件,實(shí)例化單例 Bean 等等功能,這些功能,隨著 Spring
的不斷升級(jí),功能越來越多,很多人在這里迷失了方向 :)。

簡單說就是:

低級(jí)容器 加載配置文件(從 XML,數(shù)據(jù)庫,Applet),并解析成 BeanDefinition 到低級(jí)容器中。

加載成功后,高級(jí)容器啟動(dòng)高級(jí)功能,例如接口回調(diào),監(jiān)聽器,自動(dòng)實(shí)例化單例,發(fā)布事件等等功能。

所以,一定要把 “低級(jí)容器” 和“高級(jí)容器”的區(qū)別弄清楚。不能一葉障目不見泰山。

好,當(dāng)我們創(chuàng)建好容器,就會(huì)使用 getBean 方法,獲取 Bean,而 getBean 的流程如下:

從圖中可以看出,getBean 的操作都是在低級(jí)容器里操作的。其中有個(gè)遞歸操作,這個(gè)是什么意思呢?

假設(shè) : 當(dāng) Bean_A 依賴著 Bean_B,而這個(gè) Bean_A 在加載的時(shí)候,其配置的 ref = “Bean_B” 在解析的時(shí)候只是一個(gè)占位符,被放入了 Bean_A 的屬性集合中,當(dāng)調(diào)用 getBean 時(shí),需要真正 Bean_B 注入到 Bean_A 內(nèi)部時(shí),就需要從容器中獲取這個(gè) Bean_B,因此產(chǎn)生了遞歸。

為什么不是在加載的時(shí)候,就直接注入呢?因?yàn)榧虞d的順序不同,很可能 Bean_A 依賴的 Bean_B 還沒有加載好,也就無法從容器中獲取,你不能要求用戶把 Bean 的加載順序排列好,這是不人道的。

所以,Spring 將其分為了 2 個(gè)步驟:

加載所有的 Bean 配置成 BeanDefinition 到容器中,如果 Bean 有依賴關(guān)系,則使用占位符暫時(shí)代替。

然后,在調(diào)用 getBean 的時(shí)候,進(jìn)行真正的依賴注入,即如果碰到了屬性是 ref 的(占位符),那么就從容器里獲取這個(gè)
Bean,然后注入到實(shí)例中 —— 稱之為依賴注入。

可以看到,依賴注入實(shí)際上,只需要 “低級(jí)容器” 就可以實(shí)現(xiàn)。

這就是 IoC。

所以 ApplicationContext refresh 方法里面的操作不只是 IoC,是高級(jí)容器的所有功能(包括 IoC),IoC 的功能在低級(jí)容器里就可以實(shí)現(xiàn)。

總結(jié)

說了這么多,不知道你有沒有理解Spring IoC? 這里小結(jié)一下:IoC 在 Spring 里,只需要低級(jí)容器就可以實(shí)現(xiàn),2 個(gè)步驟:

a. 加載配置文件,解析成 BeanDefinition 放在 Map 里。

b. 調(diào)用 getBean 的時(shí)候,從 BeanDefinition 所屬的 Map 里,拿出 Class 對象進(jìn)行實(shí)例化,同時(shí),如果有依賴關(guān)系,將遞歸調(diào)用 getBean 方法 —— 完成依賴注入。

上面就是 Spring 低級(jí)容器(BeanFactory)的 IoC。

至于高級(jí)容器 ApplicationContext,他包含了低級(jí)容器的功能,當(dāng)他執(zhí)行 refresh 模板方法的時(shí)候,將刷新整個(gè)容器的 Bean。同時(shí)其作為高級(jí)容器,包含了太多的功能。一句話,他不僅僅是 IoC。他支持不同信息源頭,支持 BeanFactory 工具類,支持層級(jí)容器,支持訪問文件資源,支持事件發(fā)布通知,支持接口回調(diào)等等。

可以預(yù)見,隨著 Spring 的不斷發(fā)展,高級(jí)容器的功能會(huì)越來越多。

誠然,了解 IoC 的過程,實(shí)際上為了了解 Spring 初始化時(shí),各個(gè)接口的回調(diào)時(shí)機(jī)。例如 InitializingBean,BeanFactoryAware,ApplicationListener 等等接口,這些接口的作用,筆者之前寫過一篇文章進(jìn)行介紹,有興趣可以看一下,關(guān)鍵字:Spring 必知必會(huì) 擴(kuò)展接口。

但是請注意,實(shí)現(xiàn) Spring 接口代表著你這個(gè)應(yīng)用就綁定死 Spring 了!代表 Spring 具有侵入性!要知道,Spring 發(fā)布時(shí),無侵入性就是他最大的宣傳點(diǎn)之一 —— 即 IoC 容器可以隨便更換,代碼無需變動(dòng)。而現(xiàn)如今,Spring 已然成為 J2EE 社區(qū)準(zhǔn)官方解決方案,也沒有了所謂的侵入性這個(gè)說法。因?yàn)樗褪菢?biāo)準(zhǔn),和 Servlet 一樣,你能不實(shí)現(xiàn) Servlet 的接口嗎?: -)

好了,下次如果再有面試官問 Spring IoC 初始化過程,就再也不會(huì)含糊其詞、支支吾吾了。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/75875.html

相關(guān)文章

  • 記一次慘烈的阿里面試經(jīng)歷

    摘要:當(dāng)我們的需求出現(xiàn)變動(dòng)時(shí),工廠模式會(huì)需要進(jìn)行相應(yīng)的變化??偨Y(jié)來說,要想成功進(jìn)行一次阿里巴巴的面試,你需要了解甚至掌握以下內(nèi)容語言,尤其是線程原理數(shù)據(jù)庫事務(wù),加鎖,重點(diǎn)分布式設(shè)計(jì)模式可以說是涉及范圍非常廣了。 showImg(https://segmentfault.com/img/bV8cSY?w=576&h=432); 前言 今天本是一個(gè)陽光明媚,鳥語花香的日子。于是我決定在逛街中感受...

    Eastboat 評(píng)論0 收藏0
  • 一名3年工作經(jīng)驗(yàn)的java程序員應(yīng)該具備的職業(yè)技能

    摘要:一名年工作經(jīng)驗(yàn)的程序員應(yīng)該具備的技能,這可能是程序員們比較關(guān)心的內(nèi)容。數(shù)據(jù)結(jié)構(gòu)和算法分析數(shù)據(jù)結(jié)構(gòu)和算法分析,對于一名程序員來說,會(huì)比不會(huì)好而且在工作中能派上用場。 一名3年工作經(jīng)驗(yàn)的Java程序員應(yīng)該具備的技能,這可能是Java程序員們比較關(guān)心的內(nèi)容。我這里要說明一下,以下列舉的內(nèi)容不是都要會(huì)的東西—-但是如果你掌握得越多,最終能得到的評(píng)價(jià)、拿到的薪水勢必也越高。 1、基本語法 這包括...

    renweihub 評(píng)論0 收藏0
  • 技術(shù)經(jīng)理:求求你,別再亂改數(shù)據(jù)庫連接池的大小了!

    摘要:你僅僅需要一個(gè)大小為數(shù)據(jù)庫連接池,然后讓剩下的業(yè)務(wù)線程都在隊(duì)列里等待就可以了。你應(yīng)該經(jīng)常會(huì)看到一些用戶量不是很大的應(yīng)用中,為應(yīng)付大約十來個(gè)的并發(fā),卻將數(shù)據(jù)庫連接池設(shè)置成,的情況。請不要過度配置您的數(shù)據(jù)庫連接池的大小。 文章翻譯整理自: https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing歡迎關(guān)注個(gè)人微信公眾...

    darkbug 評(píng)論0 收藏0
  • 技術(shù)經(jīng)理:求求你,別再亂改數(shù)據(jù)庫連接池的大小了!

    摘要:你僅僅需要一個(gè)大小為數(shù)據(jù)庫連接池,然后讓剩下的業(yè)務(wù)線程都在隊(duì)列里等待就可以了。你應(yīng)該經(jīng)常會(huì)看到一些用戶量不是很大的應(yīng)用中,為應(yīng)付大約十來個(gè)的并發(fā),卻將數(shù)據(jù)庫連接池設(shè)置成,的情況。請不要過度配置您的數(shù)據(jù)庫連接池的大小。 文章翻譯整理自: https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing歡迎關(guān)注個(gè)人微信公眾...

    蘇丹 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<