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