BeanFactory爲Spring的IoC功能提供底層的基礎,可是它只直接用於與其它第三發框架集成,而且對於使用它的大部分Spring用戶來講都是歷史緣由形成的。BeanFactory和相關接口,例如BeanFactoryAware、InitializingBean、DisposableBean,仍然在Spring被提供,爲了向後兼容與Spring集成的大量第三發框架。不少時候第三方組件不能使用更現代的方式例如@PostConstruct或@PreDestory,通常是爲了保持對JDK 1.4的兼容或去除對JSR-250的依賴。框架
本節提供了額外的背景關於BeanFactory與ApplicationContext之間的不一樣之處和如何經過典型的單例查找來直接獲取IoC容器。工具
應使用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。接口
最好使用依賴注入風格編寫絕大部分應用代碼,這些代碼在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定位器。內存