BeanFactory是spring中比較原始的Factory。如XMLBeanFactory就是一種典型的BeanFactory。原始的BeanFactory無(wú)法支持spring的許多插件,如AOP功能、Web應(yīng)用等。
ApplicationContext接口,它由BeanFactory接口派生而來(lái),ApplicationContext包含BeanFactory的所有功能,通常建議比BeanFactory優(yōu)先。
用處:
平常在使用的 Spring 的過(guò)程中,我想大家應(yīng)該用到的都是 ApplicationContext 用來(lái)讀取配置文件,然后啟動(dòng) Spring 容器。但是,我們使用過(guò)程中,肯定也知道存在 Beanfactory 的存在。那么我們?yōu)槭裁炊际鞘褂?ApplicationContext,而非 BeanFactory 的呢?
兩種方式獲取Bean:
現(xiàn)在寫(xiě)個(gè)用 BeanFactory 來(lái)獲取定義的 bean 程序。
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
BeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
beanDefinitionReader.loadBeanDefinitions(new ClassPathResource("applicationContext.xml"));
DemoServiceImpl demo = (DemoServiceImpl) beanFactory.getBean("demo");
現(xiàn)在我們對(duì)比用 ApplicationContext 寫(xiě)一個(gè)獲取 bean 的程序:
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
DemoService demo = (DemoService) ctx.getBean("demo");
從上面兩個(gè)程序?qū)Ρ瓤梢钥闯?,使?Beanfactory 來(lái)獲取 Bean ,我們還額外實(shí)現(xiàn)相關(guān)類。這些類我們使用 ApplicationContext 根本無(wú)需實(shí)現(xiàn)。那么為什么是這樣的那?接下去我們查看 Spring 相關(guān)的源碼。
Spring源碼
上面兩個(gè)程序我們看出 ApplicationContext 與 BeanFactory 都存在 getBean 這個(gè)核心方法。這個(gè)時(shí)候自然想到。這兩個(gè)類是否實(shí)現(xiàn)了相同的接口。使用 Idea 類圖功能,得到了下面了關(guān)系圖。

從這個(gè)圖中我們清晰看出 ApplicationContext 繼承 BeanFactory,自然的 ApplicationContext 就擁有了 BeanFactory 的相關(guān)方法了。然后再看其實(shí)現(xiàn)類相關(guān)代碼,畫(huà)出下面一張類圖。

從這張類圖可以看出,AbstractRefreshableApplicationContext 存在的 Beanfactory 屬性,我們?cè)俨榭?ApplicationContext getBean 方法實(shí)際上最后委托 BeanFactory 的 getBean 方法。
1、利用MessageSource進(jìn)行國(guó)際化
BeanFactory是不支持國(guó)際化功能的,因?yàn)锽eanFactory沒(méi)有擴(kuò)展Spring中MessageResource接口。相反,由于ApplicationContext擴(kuò)展了MessageResource接口,因而具有消息處理的能力(i18N)。
2、強(qiáng)大的事件機(jī)制(Event)
基本上牽涉到事件(Event)方面的設(shè)計(jì),就離不開(kāi)觀察者模式。不明白觀察者模式的朋友,最好上網(wǎng)了解下。因?yàn)椋@種模式在java開(kāi)發(fā)中是比較常用的,又是比較重要的。
ApplicationContext的事件機(jī)制主要通過(guò)ApplicationEvent和ApplicationListener這兩個(gè)接口來(lái)提供的,和java swing中的事件機(jī)制一樣。即當(dāng)ApplicationContext中發(fā)布一個(gè)事件的時(shí),所有擴(kuò)展了ApplicationListener的Bean都將會(huì)接受到這個(gè)事件,并進(jìn)行相應(yīng)的處理。
Spring提供了部分內(nèi)置事件,主要有以下幾種:
ContextRefreshedEvent :ApplicationContext發(fā)送該事件時(shí),表示該容器中所有的Bean都已經(jīng)被裝載完成,此ApplicationContext已就緒可用
ContextStartedEvent:生命周期 beans的啟動(dòng)信號(hào)
ContextStoppedEvent: 生命周期 beans的停止信號(hào)
ContextClosedEvent:ApplicationContext關(guān)閉事件,則context不能刷新和重啟,從而所有的singleton bean全部銷毀(因?yàn)閟ingleton bean是存在容器緩存中的)
雖然,spring提供了許多內(nèi)置事件,但用戶也可根據(jù)自己需要來(lái)擴(kuò)展spriong中的事物。注意,要擴(kuò)展的事件都要實(shí)現(xiàn)ApplicationEvent接口。
3.底層資源的訪問(wèn)
ApplicationContext擴(kuò)展了ResourceLoader(資源加載器)接口,從而可以用來(lái)加載多個(gè)Resource,而B(niǎo)eanFactory是沒(méi)有擴(kuò)展ResourceLoader
4.其它區(qū)別
1).BeanFactroy采用的是延遲加載形式來(lái)注入Bean的,即只有在使用到某個(gè)Bean時(shí)(調(diào)用getBean()),才對(duì)該Bean進(jìn)行加載實(shí)例化,這樣,我們就不能發(fā)現(xiàn)一些存在的Spring的配置問(wèn)題。而ApplicationContext則相反,它是在容器啟動(dòng)時(shí),一次性創(chuàng)建了所有的Bean,也可以選擇開(kāi)啟懶加載。這樣,在容器啟動(dòng)時(shí),我們就可以發(fā)現(xiàn)Spring中存在的配置錯(cuò)誤。
2).BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但兩者之間的區(qū)別是:BeanFactory需要手動(dòng)注冊(cè),而ApplicationContext則是自動(dòng)注冊(cè)