BeanFactory
和FactoryBean
都是Spring框架中重要的接口,名字很像,但是功能上是有很大的不同的。
先上結論
相同點
- 都是接口
- 都沒有父接口,是Spring框架中比較基礎的接口
不同點
BeanFactory
正如其接口名的暗示,是一個工廠類,用於管理(生成)Bean。也可以認爲其實現類就是一個IOC容器。FactoryBean
是一個Bean, 而該Bean的功能是控制其他Bean實例化的邏輯。- 因此,
FactoryBean
類型的對象也是由BeanFactory
管理的
BeanFactory
- BeanFactory定義了IOC容器的最基本形式,並提供了IOC容器應遵守的的最基本的接口,也就是Spring IOC容器所遵守的最底層和最基本的編程規範。
- 它的職責包括:實例化、定位、配置應用程序中的對象及建立這些對象間的依賴。
- 在Spring源碼中,BeanFactory只是個接口,並不是IOC容器的具體實現。但是Spring框架給出了很多種實現,如 DefaultListableBeanFactory,XmlBeanFactory, ApplicationContext等,都是附加了某種功能的實現。
- 該接口的方法如下,可以看出該接口實現的主要功能就是從IOC容器中獲取Bean:
FactoryBean
一般情況下,Spring通過反射機制利用標籤的class屬性指定實現類實例化Bean,但是在某些情況下,實例化Bean過程比較複雜,如果按照傳統的方式,則需要在標籤中提供大量的配置信息。配置方式的靈活性是受限的,這時採用代碼的方式可能會得到一個簡單的方案。
另外還有一些情況下,要使用第三方庫/框架提供的Bean時,這些Bean的實例化過程不應該由使用者插手,而Spring框架本身又無從得知這些第三方Bean的實例化邏輯,因此需要某種方式將Bean的實例化邏輯引入到Spring框架中。
Spring爲此提供了一個org.springframework.bean.factory.FactoryBean
的工廠類接口,用戶/第三方庫設計者可以通過實現該接口定製實例化Bean的邏輯。
實現 FactoryBean
接口需要實現三個方法,分別是isSingleton()
, getObject()
, getObjectType()
,其中 getObject()
方法返回的就是它產生的Bean實例。
FactoryBean的設計體現了“裝飾者模式”的設計模式,其一個典型的實現是是Mybaits中的SqlSessionFactory
類。
FactoryBean生成的Bean的名字
對於實現了FactoryBean
接口的Bean,Spring框架對其命名稍有不同。即代碼中爲實現了FactoryBean
接口的Bean指定的名字將會命名給該FactoryBean
生產出的Bean,而這個FactoryBean
實例的Bean name是在指定的名字前加一個"&"符號。
對Bean name的實驗
- 創建一個Bean類Foo
- 創建一個FactoryBean的實現類CustomFactoryBean,其中getObject()方法就返回一個Foo實例,並通過@Component實例將該類交給IOC容器管理
- 在啓動類中,按名稱獲取該工廠Bean,並執行其方法。但是卻有報錯。說明,在IOC容器中,名爲"customFactoryBean"的Bean並不是CustomFactoryBean類型的。
- 那究竟是什麼類型?在啓動類中用以下代碼探究名爲"customFactoryBean"的Bean到底是什麼類型
輸出爲:The class of bean is: class cn.litiezhu.explorespring.dao.Foo
。是在CustomFactoryBean.getObject()
方法的返回類型。 - 通過以下代碼探索CustomFactoryBean類型的Bean在容器中的名字
輸出爲:&customFactoryBean
- 那麼如果不給CustomFactoryBean指定名字呢?通過實驗會發現,結果還是一樣的,即將
CustomFactoryBean
的默認名字customFactoryBean
命名給了其生產的Foo
類型的Bean。