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定位器。内存