日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring IoC(一)IoC容器的设计与实现:BeanFactory与ApplicationContext

發(fā)布時(shí)間:2024/9/30 javascript 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring IoC(一)IoC容器的设计与实现:BeanFactory与ApplicationContext 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在寫B(tài)eanFactory與ApplicationContext 之前,我想先簡(jiǎn)單聊一聊Spring IoC 容器,希望能給大家一個(gè)參考。如果你對(duì)這反面的知識(shí)比較了解,可以直接跳過。

(一)Spring IoC 容器概述

1.1IOC & DI

控制反轉(zhuǎn)(Inversion of Control):其思想是反轉(zhuǎn)資源獲取的方向。 傳統(tǒng)的資源查找方式要求組件向容器發(fā)起請(qǐng)求查找資源。 作為回應(yīng), 容器適時(shí)的返回資源。
而應(yīng)用了 IOC 之后, 則是容器主動(dòng)地將資源推送給它所管理的組件, 組件所要做的僅是選擇一種合適的方式來接受資源。 這種行為也被稱為查找的被動(dòng)形式。
如果要確定是哪些方面被反轉(zhuǎn)了,結(jié)論是:依賴對(duì)象的獲得被反轉(zhuǎn)了。
它包括依賴注入(Dependency Injection)和依賴查找(Dependency Lookup)。

依賴注入(Dependency Injection) : IOC 的另一種表述方式。即組件以一些預(yù)先定義好的方式接受來自如容器的資源注入。 相對(duì)于 IOC 而言,這種表述更直接。

1.2IoC 容器的優(yōu)點(diǎn)

在Spring 中,IoC容器是實(shí)現(xiàn)控制反轉(zhuǎn)這個(gè)理念的載體,它可以在對(duì)象生成或初始化時(shí)直接將數(shù)據(jù)注入到對(duì)象中。這種依賴注入可以是遞歸進(jìn)行的,對(duì)象被逐層注入。IoC 容器把對(duì)象的依賴關(guān)系有序的建立起來,簡(jiǎn)化了對(duì)象依賴關(guān)系的管理,在很大程度上簡(jiǎn)化了面向?qū)ο笙到y(tǒng)的復(fù)雜性。

通過使用IoC 容器,對(duì)象依賴關(guān)系的管理被反轉(zhuǎn)了,被反轉(zhuǎn)到IoC 容器中,對(duì)象之間的相互依賴關(guān)系由IoC 容器管理,并由IoC 容器完成對(duì)象的注入。這在很大程度上簡(jiǎn)化了應(yīng)用的開發(fā),把對(duì)象從復(fù)雜的對(duì)象依賴關(guān)系解放出來。

IoC 容器可以把資源的獲取方向反轉(zhuǎn),讓IoC 容器主動(dòng)管理這些依賴關(guān)系,將這些關(guān)系注入到組件中,可以使依賴關(guān)系的適配和管理變得更加靈活。

如果合作對(duì)象的引用或依賴關(guān)系的管理由具體對(duì)象來完成,會(huì)導(dǎo)致代碼的高度耦合和可測(cè)試性降低,這對(duì)復(fù)雜的面向?qū)ο笙到y(tǒng)的設(shè)計(jì)是非常不利的。有了IoC 容器之后,這些依賴關(guān)系可以通過把對(duì)象的依賴注入交給框架或者IoC 容器來完成,這種從具體對(duì)象手中交出控制的做法是非常有價(jià)值的,它可以在解耦代碼的同時(shí)提高代碼的可測(cè)試性。

(二)BeanFactory與 ApplicationContext

2.1IoC 容器系列

在Spring IoC 容器的設(shè)計(jì)中,有兩個(gè)主要的容器系列,一個(gè)是實(shí)現(xiàn)BeanFactory 接口的簡(jiǎn)單容器系列,這系列容器只實(shí)現(xiàn)的容器的基本功能;另一個(gè)是ApplicationContext 應(yīng)用上下文,它作為容器的高級(jí)系列而存在。應(yīng)用上下文在簡(jiǎn)單容器的基礎(chǔ)上,增加了許多面向框架的特性,同時(shí)對(duì)應(yīng)用環(huán)境做了許多適配。有了這兩種基本的容器系列,基本上就可以滿足用戶對(duì)IoC 容器使用的大部分需求了。

我們可以在代碼的角度來查看一下這些容器的設(shè)計(jì)情況。

通過繼承結(jié)構(gòu)我們可以發(fā)現(xiàn)BeanFactory 是作為一個(gè)最基本的接口類存在于Spring IoC 容器體系中的。這個(gè)繼承結(jié)構(gòu)圖可以作為參考,下面主要介紹BeanFactory與 ApplicationContext。

2.2BeanFactory

2.2.1BeanFactory 應(yīng)用場(chǎng)景

BeanFactory 提供了最基本的IoC 容器的實(shí)現(xiàn),關(guān)于這些功能的定義,如下:

BeanFactory 接口定義了IoC 容器的最基本形式,并且提供了IoC 容器所應(yīng)該遵守的最基本的服務(wù)契約。同時(shí),這也是IoC 容器所應(yīng)該遵守的最底層和最基本的編程規(guī)范,勾勒出了最基本的IoC 容器輪廓。很顯然BeanFactory 只是一個(gè)接口,所以并沒有給出方法的實(shí)現(xiàn)。其中DefaultListableBeanFactory、XmlBeanFactory 和ApplicationContext都可以看作是容器體系中的具體容器產(chǎn)品。在Spring 中,所有的Bean 都是由BeanFactory 來進(jìn)行管理的。

BeanFactory 中設(shè)計(jì)了getBean() 方法,這個(gè)方法是IoC 容器API 的主要方法,通過這個(gè)方法,可以獲取到由IoC 容器所管理的Bean。通過上面的圖我們可以知道,BeanFactory 支持多種方式獲取Bean。下面來具體了解一下其中一些方法的作用。

  • containsBean() :可以讓用戶判斷容器中是否含有指定名字的Bean。
  • isSingleton() :查詢指定名字的Bean 是不是單例的。默認(rèn)情況下,Spring IoC 容器中的Bean 是單例的。用戶可以在BeanDefinition 中指定。
  • isPrototype():查詢指定名字的Bean 是不是原型的。與isSingleton() 方法類似。
  • isTypeMatch():用來查詢指定名字的Bean 的Class 類型是否是特定的Class 類型。
  • getType():獲取指定名字的Bean 的Class 類型。
  • getAliases():獲取指定名字的Bean 的所有別名。這些別名可以在BeanDefinition 定義。

這些定義的接口方法規(guī)劃了IoC 容器的基本特征。BeanFactory 允許使用不同的方式來檢索Bean,從而將以前用戶自己創(chuàng)建與管理Bean 的方式中解放出來。這些檢索方法是Spring IoC 容器的最基本的入口。

2.2.2BeanFactory 容器的設(shè)計(jì)原理

BeanFactory 接口提供了使用IoC 容器的規(guī)范。在這基礎(chǔ)上,Spring 還提供了一些符合這個(gè)容器接口的具體實(shí)現(xiàn)。這里以XMLBeanFactory 為例(現(xiàn)在這個(gè)類已經(jīng)被廢棄了)來簡(jiǎn)單說明IoC 容器的設(shè)計(jì)原理。下面是這個(gè)類的部分繼承結(jié)構(gòu)。

XMLBeanFactory 作為IoC 容器最底層的實(shí)現(xiàn),與ApplicationContext 相比有明顯的特點(diǎn):它只提供最基本的IoC 容器的功能。我們可以把BeanFactory 實(shí)現(xiàn)時(shí)IoC 容器的基本形式,而各種ApplicationContext 的實(shí)現(xiàn)是IoC 容器的高級(jí)變現(xiàn)形式。接下來就從XMLBeanFactory 入手來簡(jiǎn)要分析IoC 容器是如何實(shí)現(xiàn)的。下面是去掉注釋后的XMLBeanFactory 底層源碼。

public class XmlBeanFactory extends DefaultListableBeanFactory {private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);public XmlBeanFactory(Resource resource) throws BeansException {this(resource, null);}public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {super(parentBeanFactory);this.reader.loadBeanDefinitions(resource);} }

XMLBeanFactory 繼承自DefaultListableBeanFactory ,后者這個(gè)類非常重要,是經(jīng)常可以用到的一個(gè)IoC 容器的實(shí)現(xiàn)。DefaultListableBeanFactory 這個(gè)包含了基本IoC 容器所具有的的重要功能,也是很多IoC 容器系列都會(huì)用到的一個(gè)基本IoC 產(chǎn)品。比如在ApplicationContext 中就會(huì)用到它。實(shí)現(xiàn)涉及到了1000多行代碼,有很多的方法,這里不方便貼出,有興趣的話大家可以自己查看。

在Spring 中實(shí)際上把DefaultListableBeanFactory 作為一個(gè)默認(rèn)的功能完整的IoC 容器來使用。XMLBeanFactory 在繼承了DefaultListableBeanFactory 的同時(shí),擴(kuò)展了其中的方法。由它的名字我們可以看出,XMLBeanFactory 是一個(gè)與XML 文件相關(guān)的BeanFactory。

這個(gè)類是如何讀取XML 的呢?其實(shí),對(duì)于XML 文件的信息的讀取并不是由XMLBeanFactory 直接完成的。在上面的源碼中,可以看出在XMLBeanFactory 中定義并初始化了一個(gè)XmlBeanDefinitionReader 對(duì)象,有了這個(gè)reader 對(duì)象,那些以XML 方式定義的BeanDefinition 就有了處理的地方。實(shí)際上,對(duì)于XML 形式的信息處理是由XmlBeanDefinitionReader 來完成的。

在XMLBeanFactory 構(gòu)造函數(shù)中,需要指定BeanDefinition 的信息來源。Resource 是Spring 用來封裝I/O 操作的接口,由其具體的實(shí)現(xiàn)類來加載XML 文件,從而來完成Bean 的初始化與依賴注入過程。下面是Resource 相關(guān)的繼承結(jié)構(gòu)圖。

XMLBeanFactory 的功能是建立在DefaultListableBeanFactory 類基礎(chǔ)上的,并在這個(gè)基本容器的基礎(chǔ)上實(shí)現(xiàn)了一些關(guān)于XML 文件的操作。XMLBeanFactory 中的源碼很好理解:在XMLBeanFactory 的構(gòu)造函數(shù)中得到需要的Resource 對(duì)象對(duì)XmlBeanDefinitionReader 對(duì)象初始化,以及使用這個(gè)對(duì)象來完成loadBeanDefinitions() 方法的調(diào)用,loadBeanDefinitions() 同時(shí)也是IoC 容器初始化的重要組成部分。

通過對(duì)過程的分析,我們就可以總結(jié)一下IoC 容器的使用過程(這里通過代碼的方式總結(jié)),這個(gè)過程可以參考上面的XmlBeanFactory 源碼實(shí)現(xiàn)。

ClassPathResource res = new ClassPathResource("bean.xml"); DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory); reader.loadBeanDefinitions(res);

過程分析:

  • 創(chuàng)建IoC 配置文件的抽象信息,這個(gè)抽象資源包含了BeadDefinition 的定義信息。
  • 創(chuàng)建一個(gè)BeanFactory,這里以DefaultListableBeanFactory 為例。
  • 創(chuàng)建一個(gè)BeadDefinition 的讀取器,通過一個(gè)回調(diào)配置給BeanFactory。
  • 從定義好的資源位置讀取配置信息,具體的解析過程由XmlBeanDefinitionReader 對(duì)象來完成。在完成載入和注冊(cè)Bean之后,需要的IoC 容器就建立起來了。這時(shí)候就可以直接使用了。
  • 2.3ApplicationContext

    2.3.1ApplicationContext 應(yīng)用場(chǎng)景

    在Spring 中,系統(tǒng)已經(jīng)為用戶提供了定義好的容器的實(shí)現(xiàn),從而簡(jiǎn)化我們的開發(fā)。相比那些簡(jiǎn)單擴(kuò)展BeanFactory 的基本IoC 容器,我們常用的是AppliCationContext,它除了提供了前面介紹的基本IoC 容器功能外,還提供了一些附加功能,因此讓用戶更方便的使用。下面是ApplicationContext 接口關(guān)系圖。

    有些接口為ApplicationContext 提供了一些BeanFactory 所不具備的新特性。

    • 支持不同的信息源。ApplicationContext 擴(kuò)展了MessageResource 接口,這些信息源的功能可以支持國(guó)際化的實(shí)現(xiàn)。
    • 訪問資源。這一特性體驗(yàn)在Resource 與ResourceLoader 上,這樣一來,我們可以從不同的地方得到Bean 定義資源。
    • 支持應(yīng)用事件。繼承了接口ApplicationEventPublisher,從而在上下文中引入了事件機(jī)制。這些事件和Bean 的生命周期的結(jié)合為Bean 的管理提供了便利。
    • 在ApplicationContext 中提供的附加服務(wù)。這些服務(wù)使得基本的IoC 容器的基本功能更加豐富。

    2.3.2ApplicationContext 容器的設(shè)計(jì)原理

    在ApplicationContext 容器中,這里以FileSystemXmlApplicationContext 的實(shí)現(xiàn)原理來說明ApplicationContext 容器的設(shè)計(jì)原理。下面是FileSystemXmlApplicationContext 的繼承結(jié)構(gòu)。

    FileSystemXmlApplicationContext 繼承自AbstractXmlApplicationContext,AbstractXmlApplicationContext 中實(shí)現(xiàn)了FileSystemXmlApplicationContext 的大部分功能。在FileSystemXmlApplicationContext 中,作為一個(gè)具體的應(yīng)用上下文,只需要實(shí)現(xiàn)和它自身相關(guān)的兩個(gè)功能。

    一個(gè)功能是,在實(shí)例化FileSystemXmlApplicationContext 時(shí),啟動(dòng)IoC 容器的refresh() 過程。主要相關(guān)代碼如下:

    public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)throws BeansException {super(parent);setConfigLocations(configLocations);if (refresh) {refresh();}}

    這個(gè)refresh() 過程會(huì)涉及到IoC 容器啟動(dòng)時(shí)的一系列復(fù)雜操作,同時(shí)對(duì)于不同的容器的實(shí)現(xiàn),這些操作都是類似的,因此在基類中將它們封裝好。所以這里只簡(jiǎn)單分析一下其調(diào)用過程。關(guān)于refresh() 在IoC 容器中的具體實(shí)現(xiàn),會(huì)在后面的博文中講述。

    另一個(gè)功能是FileSystemXmlApplicationContext 設(shè)計(jì)的相關(guān)功能,這個(gè)功能決定怎樣從文件系統(tǒng)中加載XML 的Bean 資源。下面是相關(guān)源碼:

    @Overrideprotected Resource getResourceByPath(String path) {if (path != null && path.startsWith("/")) {path = path.substring(1);}return new FileSystemResource(path);}

    通過這個(gè)過程,可以為文件系統(tǒng)中以XML 文件形式存在的BneaDefinition 做準(zhǔn)備。從而通過這個(gè)方法,得到FileSystemXmlApplicationContext 的資源定位。

    參考資料
    《Spring 技術(shù)內(nèi)幕》

    與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖

    總結(jié)

    以上是生活随笔為你收集整理的Spring IoC(一)IoC容器的设计与实现:BeanFactory与ApplicationContext的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。