BeanFactory
是Spring IoC功能的潜在基础,但是现在BeanFactory
一般仅仅用于直接集成第三方的框架,对于大多数的Spring用户来说,BeanFactory
已经算是一个历史了。BeanFactory
以及其相关的接口,包括BeanFactoryAware
,InitializingBean
,DisposableBean
,出于跟大量第三方框架兼容的问题,仍然存在。因为很多时候,第三方组件还不能使用形如@PostConstruct
或者@PreDestroy
这类的注解,为了继续支持JDK1.4以及避免依赖于JSR-250标准。
下面将描述BeanFactory
和ApplicationContext
之间的一些异同以及如何通过典型的单例查找访问IoC容器。
BeanFactory
还是 ApplicationContext
?
最好还是使用ApplicationContext
除非真的有不得不使用BeanFactory
的理由。
因为ApplicationContext
包含了BeanFactory
的所有功能,所以它更优于BeanFactory
。只有少数情况,比如嵌入式应用环境中,运行应用的设备资源受限,内存要求更为严格,仅仅差几k几十k内存开销都会对应用产生影响的情况,才需要权衡是否使用BeanFactory
。所以,在绝大多数的典型情况之中,开发者肯定还是使用ApplicationContext
最好。Spring在BeanPostProcessor
这个扩展点上是重度用户,如果开发者仅仅使用BeanFactory
的话,相当多的功能,诸如事务,AOP都将不会生效。这个时候,就会让人很疑惑,因为配置都是正确的。
下表列出了所有BeanFactory
和ApplicationContext
接口和实现的一些特性:
Feature | BeanFactory |
ApplicationContext |
---|---|---|
Bean的实例化和装载 | 支持 | 支持 |
自动的BeanPostProcessor 注册 |
不支持 | 支持 |
自动的BeanFactoryPostProcessor 注册 |
不支持 | 支持 |
MessageSource 国际化 |
不支持 | 支持 |
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);
可以看到,上面的两种方式,Bean的注册过程都是相当繁琐的,这也是为什么要推荐使用ApplicationContext
而非BeanFactory
的原因。而且,尤其是在需要使用BeanFactoryPostProcessor
,BeanPostProcessor
以及占位符替换,AOP等功能的时候,ApplicationContext
会比BeanFactory
更为方便。