IoC容器16——BeanFactory

BeanFactory爲Spring的IoC功能提供底層的基礎,可是它只直接用於與其它第三發框架集成,而且對於使用它的大部分Spring用戶來講都是歷史緣由形成的。BeanFactory和相關接口,例如BeanFactoryAware、InitializingBean、DisposableBean,仍然在Spring被提供,爲了向後兼容與Spring集成的大量第三發框架。不少時候第三方組件不能使用更現代的方式例如@PostConstruct或@PreDestory,通常是爲了保持對JDK 1.4的兼容或去除對JSR-250的依賴。框架

本節提供了額外的背景關於BeanFactory與ApplicationContext之間的不一樣之處和如何經過典型的單例查找來直接獲取IoC容器。工具

1 BeanFactory 仍是 ApplicationContext

應使用ApplicationContext除非有一個好的理由不這麼作。post

由於ApplicationContext包含了BeanFactory的全部功能,一般推薦不使用BeanFactory,除了幾種狀況,例如在資源有限的設備上運行的嵌入式應用程序,其內存消耗可能相當重要而且額外的千字節可能會有很大的不一樣。對於大多數典型的企業級應用和系統,ApplicationContext是首選。Spring大量使用了BeanPostProcessor擴展點(以實現代理等等)。若是僅僅想使用普通的BeanFactory,大量的支持例如事務和AOP都不會生效,至少在不進行任何額外操做時不會生效。這種狀況可能讓人迷惑,由於事實上配置並無發生錯誤。代理

下面的表格列出了BeanFactory和ApplicationContext接口和實現提供的功能。code

功能 BeanFactory ApplicationContext
Bean實例化和裝配 Yes Yes
自動註冊BeanPostProcessor No Yes
自動註冊BeanFactoryPostProcessor No Yes
方便的獲取MessageSource(國際化使用) No Yes
ApplicationEvent發佈 No Yes

使用BeanFactory實現須要明確的註冊bean後處理器,像下面同樣編寫代碼:xml

DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
// populate the factory with bean definitions

// now register any needed BeanPostProcessor instances
MyBeanPostProcessor postProcessor = new MyBeanPostProcessor();
factory.addBeanPostProcessor(postProcessor);

// now start using the factory

使用BeanFactory實現須要明確的註冊BeanFactoryPostProcessor,像下面同樣編寫代碼:對象

DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(new FileSystemResource("beans.xml"));

// bring in some property values from a Properties file
PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer();
cfg.setLocation(new FileSystemResource("jdbc.properties"));

// now actually do the replacement
cfg.postProcessBeanFactory(factory);

在這兩個例子中,明確的註冊步驟是繁瑣的,這是其中一個在絕大多數Spring支持的應用程序中推薦各類ApplicationContext實現而不是普通BeanFactory實現的緣由,特別是當使用BeanFactoryPostProcessor和BeanPostProcessor時。這些ApplicationContext實現了重要的功能例如屬性佔位符替換和AOP。接口

2 粘合代碼和壞單例

最好使用依賴注入風格編寫絕大部分應用代碼,這些代碼在Spring IoC容器以外,當被建立時由容器提供依賴關係,而且它們徹底不知道容器的存在。然而對於少許的粘合層代碼(???原文 for the small glue layers code),有時須要與其它代碼綁定在一塊兒,就須要用單例(或準單例)的方式來訪問一個Spring IoC容器。例如,第三方代碼可能嘗試直接構建新對象(使用Class.forName()的方式),而不從Spring IoC容器獲取這些對象。若是由第三方代碼建立的對象是一個stub(???存根)或代理,而後使用單例的方式訪問Spring容器來獲取被代理的真正對象,那麼主要的代碼依然達成了控制反轉(這個對象從容器獲得)。所以大部分代碼仍然不知道容器或者如何訪問它,而且保持了與其它代碼的解耦和隨之而來的全部好處。EJB可使用這種存根/代理的方法來代理一個從Spring IoC容器檢索出來的普通Java對象。雖然Spring IoC容器自己不必定非要是一個單例,但在內存使用或初始化時間(在Spring IoC容器中使用bean例如一個Hibernate SessionFactory)方面,每一個bean使用本身的、非單例Spring IoC容器是不切實際的。事務

用服務定位器的方法檢索應用上下文有時是獲取共享Spring管理組件的惟一方式,例如在EJB 2.1環境中或者當你想共享一個ApplicationContext做爲另外一個WAR文件的WebApplicationContext的父上下文。在這種狀況下須要查看工具類ContextSingletonBeanFactoryLocator定位器。內存

相關文章
相關標籤/搜索