?
本文檔使用 PHP中文網(wǎng)手冊(cè) 發(fā)布
一個(gè)應(yīng)用中的大多數(shù)代碼最好寫(xiě)成依賴注入(控制反轉(zhuǎn))的風(fēng)格,這樣代碼就和Spring IoC容器無(wú)關(guān),它們?cè)诒粍?chuàng)建時(shí)從容器得到自己的依賴,并且完全不知道容器的存在。然而,對(duì)于少量需要與其它代碼粘合的粘合層代碼來(lái)說(shuō),有時(shí)候就需要以一種singleton(或者類似singleton)的方式來(lái)訪問(wèn)Spring IoC容器。例如,第三方的代碼可能試圖(以Class.forName()
的方式)直接構(gòu)造一個(gè)新的對(duì)象,但無(wú)法強(qiáng)制它們從Spring IoC容器中得到這些對(duì)象。如果第三方代碼構(gòu)造的對(duì)象只是一個(gè)小stub或proxy,并且使用singleton方式訪問(wèn)Spring IoC容器來(lái)獲得真正的對(duì)象,那么大多數(shù)的代碼(由容器產(chǎn)生的對(duì)象)仍然可以使用控制反轉(zhuǎn)。因此大多數(shù)的代碼依然不需要知道容器的存在,或者它如何被訪問(wèn),并保持與其它代碼的解耦,這樣所帶來(lái)的益處是很顯然的。EJB也可以使用這種stub/proxy方案代理到由Spring IoC容器產(chǎn)生的普通的Java實(shí)現(xiàn)對(duì)象。雖然理想情況下Spring IoC容器不需要是singleton,但是如果每個(gè)bean使用它自己的non-singleton的Spring IoC容器(當(dāng)在Spring IoC容器中使用bean時(shí),如Hibernate SessionFactory
),對(duì)于內(nèi)存使用或初始化次數(shù)都是不切實(shí)際。
另一個(gè)例子,在一個(gè)多層的復(fù)雜的J2EE應(yīng)用中(比如不同的JAR,EJB,以及WAR打包成一個(gè)EAR),每一層都有自己的Spring IoC容器定義(有效地組成一個(gè)層次結(jié)構(gòu)),如果頂層只有一個(gè)web-app(WAR)的話,比較好的做法是簡(jiǎn)單地創(chuàng)建一個(gè)由不同層的XML定義文件組成的組合Spring IoC容器。所有不同的Spring IoC容器實(shí)現(xiàn)都可以以這種方式從多個(gè)定義文件構(gòu)造出來(lái)。但是,如果在頂層有多個(gè)兄弟web-apps,為每一個(gè)web-app創(chuàng)建一個(gè)Spring IoC容器,而每個(gè)ApplicationContext都包含大部分相同的底層的bean定義。因而就會(huì)因內(nèi)存使用,建bean的多個(gè)復(fù)本會(huì)花很長(zhǎng)時(shí)間初始化(比如Hibernate SessionFactory
),以及其它可能產(chǎn)生的副作用而產(chǎn)生問(wèn)題。作為另一可選的方案,象ContextSingletonBeanFactoryLocator
和SingletonBeanFactoryLocator
的類可以在需要的時(shí)候以有效的singleton方式,加載多層次的(比如一個(gè)是另一個(gè)的父親)Spring IoC容器,這些將會(huì)作為web應(yīng)用的Spring IoC容器的父容器。由此底層的bean定義只在需要的時(shí)候加載(并且只被加載一次)。
你可以查看SingletonBeanFactoryLocator和ContextSingletonBeanFactoryLocator的JavaDoc來(lái)獲得詳細(xì)的例子。正如在EJB那章所提到的,Spring為EJB提供方便使用的基類,通常使用一個(gè)non-singleton的BeanFactoryLocator
實(shí)現(xiàn),這樣在需要時(shí)就可以很容易地被SingletonBeanFactoryLocator
和ContextSingletonBeanFactoryLocator
替換。