3.16 BeanFactory

BeanFactory为Spring的IoC功能提供了底层的基础,但是它仅仅被用于和第三方框架的集成,现在对于大部分的Spring用户来说都是历史了。BeanFactory及其相关的接口,例如:BeanFactoryAware,InitializingBean,DisposableBean,在Spring中仍然有所保留,目的就是为了让大量的第三方框架和Spring集成时保持向后兼容。通常第三方组件不会更加现代的等价物,例如:@PostConstruct@PreDestroy,以便可以与JDK1.4兼容,或避免依赖JSR-250。
这部分提供了BeanFactory 和 ApplicationContext之间的背景差异以及用户怎样通过查找单例的模式来访问IoC容器。

3.16.1 BeanFactory or ApplicationContext?

尽量使用ApplicationContext除非你有更好的理由不用它。
因为ApplicationContext包括了BeanFactory的所有功能,通常也优于BeanFactory,除非一些少数的场景,例如:在受资源约束的嵌入式设备上运行一个嵌入式应用,它的内存消耗可能至关重要,并且可能会产生字节。然而,对于大多数典型的企业级应用和系统来说,ApplicationContext才是你想使用的。Spring大量使用了BeanPostProcessor扩展点(以便使用代理等)。如果你仅仅只使用简单的BeanFactory,很多的支持功能将不会有效,例如:事务和AOP,但至少不会有额外的步骤。这可能会比较迷惑,毕竟配置又没有错。

下表列了BeanFactory 和 ApplicationContext接口和实现的一些特性:

表3.9 特性矩阵

Feature BeanFactory ApplicationContext
Bean实例化/装配
BeanPostProcessor自动注册
BeanFactoryPostProcessor自动注册
MessageSource便捷访问(针对i18n)
ApplicationEvent 发布

用BeanFactory的实现来明确的注册一个bean的后置处理器,你需要写和下面类似的代码:

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实现的原因之一,特别是当使用BeanFactoryPostProcessors和BeanPostProcessors的时候。这些机制实现了一些很重要的功能,例如:属性的占位替换和AOP。