1.BeanFactory與ApplicationContext區(qū)別
容器是spring的核心,管理IOC所有的組件妻率。spring的兩種容器:
- BeanFactoy
- ApplicationContext
1.1 BeanFactory的功能
BeanFactory乱顾,以Factory結(jié)尾,表示它是一個工廠類(接口)宫静, 它負責生產(chǎn)和管理bean的一個工廠走净。在Spring中,BeanFactory是IOC容器的核心接口孤里,它的職責包括:實例化伏伯、定位、配置應(yīng)用程序中的對象及建立這些對象間的依賴扭粱。BeanFactory只是個接口,并不是IOC容器的具體實現(xiàn)震檩,但是Spring容器給出了很多種實現(xiàn)琢蛤,如 DefaultListableBeanFactory、XmlBeanFactory抛虏、ApplicationContext等博其。
注意,BeanFactory 只能管理單例(Singleton)Bean 的生命周期迂猴。它不能管理原型(prototype,非單例)Bean 的生命周期慕淡。這是因為原型 Bean 實例被創(chuàng)建之后便被傳給了客戶端,容器失去了對它們的引用。
1.2 ApplicationContext的功能
包含兩個子接口:
- ConfigurableApplicationContext
- WebApplicationContext
如果說BeanFactory是Spring的心臟沸毁,那么ApplicationContext就是完整的軀體了峰髓,ApplicationContext由BeanFactory派生而來,提供了更多面向?qū)嶋H應(yīng)用的功能息尺。在BeanFactory中携兵,很多功能需要以編程的方式實現(xiàn),而在ApplicationContext中則可以通過配置實現(xiàn)搂誉。
BeanFactorty接口提供了配置框架及基本功能徐紧,但是無法支持spring的aop功能和web應(yīng)用。而ApplicationContext接口作為BeanFactory的派生炭懊,因而提供BeanFactory所有的功能并级。而且ApplicationContext還在功能上做了擴展,相較于BeanFactorty侮腹,ApplicationContext還提供了以下的功能:
(1)MessageSource, 提供國際化的消息訪問
(2)資源訪問嘲碧,如URL和文件
(3)事件傳播特性,即支持aop特性
(4)載入多個(有繼承關(guān)系)上下文 父阻,使得每一個上下文都專注于一個特定的層次呀潭,比如應(yīng)用的web層
ApplicationContext:是IOC容器另一個重要接口钉迷, 它繼承了BeanFactory的基本功能, 同時也繼承了容器的高級功能钠署,如:MessageSource(國際化資源接口)糠聪、ResourceLoader(資源加載接口)、ApplicationEventPublisher(應(yīng)用事件發(fā)布接口)等谐鼎。
ApplicationContext常用的三個實現(xiàn)類:
- a舰蟆、ClassPathXmlApplication:把上下文文件當成類路徑資源
- b、FileSystemXmlApplication:從文件系統(tǒng)中的XML文件載入上下文定義信息
- c狸棍、XmlWebApplicationContext:從Web系統(tǒng)中的XML文件載入上下文定義信息
1.3 二者的區(qū)別
1.BeanFactroy采用的是延遲加載形式來注入Bean的身害,即只有在使用到某個Bean時(調(diào)用getBean()),才對該Bean進行加載實例化草戈,這樣塌鸯,我們就不能發(fā)現(xiàn)一些存在的Spring的配置問題。而ApplicationContext則相反唐片,它是在容器啟動時丙猬,一次性創(chuàng)建了所有的Bean。這樣费韭,在容器啟動時茧球,我們就可以發(fā)現(xiàn)Spring中存在的配置錯誤。 相對于基本的BeanFactory星持,ApplicationContext 唯一的不足是占用內(nèi)存空間抢埋。當應(yīng)用程序配置Bean較多時,程序啟動較慢督暂。
BeanFacotry延遲加載,如果Bean的某一個屬性沒有注入揪垄,BeanFacotry加載后,直至第一次使用調(diào)用getBean方法才會拋出異常逻翁;而ApplicationContext則在初始化自身是檢驗福侈,這樣有利于檢查所依賴屬性是否注入;所以通常情況下我們選擇使用 ApplicationContext卢未。
應(yīng)用上下文則會在上下文啟動后預(yù)載入所有的單實例Bean肪凛。通過預(yù)載入單實例bean ,確保當你需要的時候,你就不用等待辽社,因為它們已經(jīng)創(chuàng)建好了伟墙。
2.BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用滴铅,但兩者之間的區(qū)別是:BeanFactory需要手動注冊戳葵,而ApplicationContext則是自動注冊。(Applicationcontext比 beanFactory 加入了一些更好使用的功能汉匙。而且 beanFactory 的許多功能需要通過編程實現(xiàn)而 Applicationcontext 可以通過配置實現(xiàn)拱烁。比如后處理 bean 生蚁, Applicationcontext 直接配置在配置文件即可而 beanFactory 這要在代碼中顯示的寫出來才可以被容器識別。 )
3.beanFactory主要是面對與 spring 框架的基礎(chǔ)設(shè)施戏自,面對 spring 自己邦投。而 Applicationcontex 主要面對與 spring 使用的開發(fā)者∩帽剩基本都會使用 Applicationcontex 并非 beanFactory 志衣。
2.AnnotationConfigApplicationContext類層次
public void test01(){
AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Ch9MainConfig.class);
System.out.println(app);
TestService testService = app.getBean(TestService.class);
3.FactoryBean
3.1 BeanFactory與FactoryBean的區(qū)別
BeanFactory是個Factory,也就是IOC容器或?qū)ο蠊S猛们,F(xiàn)actoryBean是個Bean念脯。在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)來進行管理的弯淘。但對FactoryBean而言绿店,這個Bean不是簡單的Bean,而是一個能生產(chǎn)或者修飾對象生成的工廠Bean,它的實現(xiàn)與設(shè)計模式中的工廠模式和修飾器模式類似庐橙。
BeanFactory定義了IOC容器的最基本形式假勿,并提供了IOC容器應(yīng)遵守的的最基本的接口,也就是Spring IOC所遵守的最底層和最基本的編程規(guī)范怕午。在Spring代碼中废登,BeanFactory只是個接口淹魄,并不是IOC容器的具體實現(xiàn)郁惜,但是Spring容器給出了很多種實現(xiàn),如 DefaultListableBeanFactory甲锡、XmlBeanFactory兆蕉、ApplicationContext等,都是附加了某種功能的實現(xiàn)缤沦。
一般情況下虎韵,Spring通過反射機制利用<bean>的class屬性指定實現(xiàn)類實例化Bean,在某些情況下缸废,實例化Bean過程比較復雜包蓝,如果按照傳統(tǒng)的方式锥腻,則需要在<bean>中提供大量的配置信息别威。配置方式的靈活性是受限的,這時采用編碼的方式可能會得到一個簡單的方案沪铭。Spring為此提供了一個org.springframework.bean.factory.FactoryBean的工廠類接口届巩,用戶可以通過實現(xiàn)該接口定制實例化Bean的邏輯硅瞧。
FactoryBean接口對于Spring框架來說占用重要的地位,Spring自身就提供了70多個FactoryBean的實現(xiàn)恕汇。它們隱藏了實例化一些復雜Bean的細節(jié)腕唧,給上層應(yīng)用帶來了便利或辖。
3.2 FactoryBean的詳細信息
一個Bean想要實現(xiàn) FactoryBean ,必須實現(xiàn)以下三個接口:
- Object getObject():返回由FactoryBean創(chuàng)建的Bean的實例
- boolean isSingleton():確定由FactoryBean創(chuàng)建的Bean的作用域是singleton還是prototype枣接;
- getObjectType():返回FactoryBean創(chuàng)建的Bean的類型颂暇。
JamesFactoryBean類實現(xiàn)FactoryBean<Monkey>接口
public class JamesFactoryBean implements FactoryBean<Monkey> {
@Override
public Monkey getObject() throws Exception {
// TODO Auto-generated method stub
return new Monkey();
}
@Override
public Class<?> getObjectType() {
// TODO Auto-generated method stub
return Monkey.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
public class Ch6Test {
@Test
public void test01() {
AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Ch6MainConfig.class);
System.out.println("IOC容器創(chuàng)建完成........");
Object bean1 = app.getBean("jamesFactoryBean");
Object bean2 = app.getBean("jamesFactoryBean");//取Money
System.out.println("bean1的類型=" + bean1.getClass());
System.out.println(bean1 == bean2);
Object bean3 = app.getBean("&jamesFactoryBean");
System.out.println("bean3的類型=" + bean3.getClass());
結(jié)果:
bean1的類型=class com.wangzhen.ch6.bean.Monkey
true
bean3的類型=class com.wangzhen.ch6.config.JamesFactoryBean
注意:如果想通過spring拿到j(luò)amesFactoryBean,需要在名稱前加 & 符號