BeanFactory是Spring IoC功能的潛在基礎(chǔ),但是現(xiàn)在BeanFactory一般僅僅用于直接集成第三方的框架,對(duì)于大多數(shù)的Spring用戶來說,BeanFactory已經(jīng)算是一個(gè)歷史了。BeanFactory以及其相關(guān)的接口,包括BeanFactoryAware,InitializingBean,DisposableBean,出于跟大量第三方框架兼容的問題,仍然存在。因?yàn)楹芏鄷r(shí)候,第三方組件還不能使用形如@PostConstruct或者@PreDestroy這類的注解,為了繼續(xù)支持JDK1.4以及避免依賴于JSR-250標(biāo)準(zhǔn)。
下面將描述BeanFactory和ApplicationContext之間的一些異同以及如何通過典型的單例查找訪問IoC容器。
BeanFactory 還是 ApplicationContext?
最好還是使用ApplicationContext除非真的有不得不使用BeanFactory的理由。
因?yàn)?code>ApplicationContext包含了BeanFactory的所有功能,所以它更優(yōu)于BeanFactory。只有少數(shù)情況,比如嵌入式應(yīng)用環(huán)境中,運(yùn)行應(yīng)用的設(shè)備資源受限,內(nèi)存要求更為嚴(yán)格,僅僅差幾k幾十k內(nèi)存開銷都會(huì)對(duì)應(yīng)用產(chǎn)生影響的情況,才需要權(quán)衡是否使用BeanFactory。所以,在絕大多數(shù)的典型情況之中,開發(fā)者肯定還是使用ApplicationContext最好。Spring在BeanPostProcessor這個(gè)擴(kuò)展點(diǎn)上是重度用戶,如果開發(fā)者僅僅使用BeanFactory的話,相當(dāng)多的功能,諸如事務(wù),AOP都將不會(huì)生效。這個(gè)時(shí)候,就會(huì)讓人很疑惑,因?yàn)榕渲枚际钦_的。
下表列出了所有BeanFactory和ApplicationContext接口和實(shí)現(xiàn)的一些特性:
| Feature | BeanFactory |
ApplicationContext |
|---|---|---|
| Bean的實(shí)例化和裝載 | 支持 | 支持 |
自動(dòng)的BeanPostProcessor注冊(cè) |
不支持 | 支持 |
自動(dòng)的BeanFactoryPostProcessor注冊(cè) |
不支持 | 支持 |
MessageSource國(guó)際化 |
不支持 | 支持 |
ApplicationEvent的發(fā)布 |
不支持 | 支持 |
如果是在BeanFactory的實(shí)現(xiàn)下來注冊(cè)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中明確的注冊(cè)一個(gè)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的注冊(cè)過程都是相當(dāng)繁瑣的,這也是為什么要推薦使用ApplicationContext而非BeanFactory的原因。而且,尤其是在需要使用BeanFactoryPostProcessor,BeanPostProcessor以及占位符替換,AOP等功能的時(shí)候,ApplicationContext會(huì)比BeanFactory更為方便。