3.16 BeanFactory {#toc_23}

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? {#toc_24}

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

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

表3.9 特性矩阵

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

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

  1. DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
  2. // populate the factory with bean definitions
  3. // now register any needed BeanPostProcessor instances
  4. MyBeanPostProcessor postProcessor = new MyBeanPostProcessor();
  5. factory.addBeanPostProcessor(postProcessor);
  6. // now start using the factory

当使用一个BeanFactory的实现来明确的注册一个BeanFactoryPostProcessor时,你写的代码必须和下面类似:

  1. DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
  2. XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
  3. reader.loadBeanDefinitions(new FileSystemResource("beans.xml"));
  4. // bring in some property values from a Properties file
  5. PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer();
  6. cfg.setLocation(new FileSystemResource("jdbc.properties"));
  7. // now actually do the replacement
  8. cfg.postProcessBeanFactory(factory);

在这两种情况下,明确的注册步不是很方便,这也就是为什么在大多数支持Spring的应用中,ApplicationContext的各种实现都优于BeanFactory实现的原因之一,特别是当使用BeanFactoryPostProcessors和BeanPostProcessors的时候。这些机制实现了一些很重要的功能,例如:属性的占位替换和AOP。