Spring中BeanFactory?FactoryBean和ObjectFactory的三種的區(qū)別
Spring中BeanFactory FactoryBean和ObjectFactory的三種的區(qū)別
引言
關于FactoryBean 和 BeanFactory的對比文章比較多,但是對ObjectFactory的描述就比較少,今天我們對比下這三種的區(qū)別。
結論
BeanFactory就是對象工廠,Spring的底層容器,用于實例化和保存對象。
FactoryBean是一個工廠對象,用于實例化創(chuàng)建過程比較復雜的對象,對象的創(chuàng)建過程是由用戶自己控制的。
ObjectFactory是某個特定的工廠,用于在項目啟動時,延遲實例化對象,解決循環(huán)依賴問題,也就是三級緩存那里會用到,以及結合Scope,靈活方便的實現(xiàn)是否需要創(chuàng)建對象。
BeanFactory
Spring最最核心的接口,Bean工廠,從名字上就能看出這是一個工廠。它是Spring最底層的容器,負責實例化和保存Spring中的Bean。
public interface BeanFactory { String FACTORY_BEAN_PREFIX = "&"; Object getBean(String name) throws BeansException; <T> T getBean(String name, Class<T> requiredType) throws BeansException; Object getBean(String name, Object... args) throws BeansException; <T> T getBean(Class<T> requiredType) throws BeansException; <T> T getBean(Class<T> requiredType, Object... args) throws BeansException; <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType); <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType); boolean containsBean(String name); boolean isSingleton(String name) throws NoSuchBeanDefinitionException; boolean isPrototype(String name) throws NoSuchBeanDefinitionException; ## 方法很多,不再贅述 }
FactoryBean
public interface FactoryBean<T> { //返回的對象實例 T getObject() throws Exception; //Bean的類型 Class<?> getObjectType(); //true是單例,false是非單例 在Spring5.0中此方法利用了JDK1.8的新特性變成了default方法,返回true boolean isSingleton(); }
我們觀察到FactoryBean接口有三個方法。getObject
用來返回實例化后的對象。getObjectType
用來返回對象的類型。isSingleton
用來標識對象是否為單例的,這里默認為true,Spring會將實例化后的對象放入BeanFactory容器中。
從方法上,能推測出,這個凡是實現(xiàn)了FactoryBean接口的類,負責返回這個java類的實例化對象。
從設計模式的角度來看這就是典型的工廠方法模式。由一個特定的工廠來生產(chǎn)特定的java類的實例化對象。
那么這種寫法有哪些好處呢?
正常情況下,Spring中在實例化對象的時候,都是由BeanFactory從上下文中獲取BeanDefinition信息,然后通過反射,調(diào)用這個java類的構造方法進行實例化。而現(xiàn)在這種形式,我們相當于將實例化的功能交給了FactoryBean去實現(xiàn)。這種方式主要使用在一些比較復雜的實例化過程中,并非簡單地設置一些參數(shù)或者設置的參數(shù)過多,過程中可能需要做一些復雜的解析、判斷和邏輯處理,這個時候交由Spring去通過反射進行實例化可能就不太靈活了,
Spring容器中有兩種Bean,一種是普通的Bean對象,一種是實現(xiàn)了FactoryBean的工廠Bean對象。如果從BeanFactory中getBean的時候,獲取到的Bean對象是工廠Bean,會自動的調(diào)用它的getObject方法返回真實實例化對象。
如果就是需要獲取FactoryBean對象,需要在getBean的時候加上前綴’&'。
Spring自身就對FactoryBean有70多種實現(xiàn),比較常見的就是Proxy,Jndi等場景。
AOP中使用的ProxyFactoryBean。
Dubbo中使用的ReferenceBean。
Mybatis中使用的SqlSessionFactoryBean。
FactoryBean的著重于自定義創(chuàng)建對象過程,由BeanFactory通過FactoryBean來獲取目標對象,而如果是isSingleton返回true的話spring會利用單例緩存來緩存通過FactoryBean創(chuàng)建的對象。
ObjectFactory
public interface ObjectFactory<T> { //返回的對象實例 T getObject() throws BeansException; }
這用于延遲查找的場景,它就是一個普通工廠,當?shù)玫?ObjectFactory 對象時,相當于 Bean 沒有被創(chuàng)建,只有當 getObject() 方法時,才會觸發(fā) Bean 實例化等生命周期。
一方面在循環(huán)依賴的時候,用于延遲初始化,見org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
中調(diào)用addSingletonFactory
方法,會把ObjectFactory的Lambda表達式放入三級緩存。
另一方面,在AbstractBeanFacotry在doGetBean處的使用時,將創(chuàng)建對象的步驟封裝到ObjectFactory中 交給自定義的Scope來選擇是否需要創(chuàng)建對象來靈活的實現(xiàn)scope。除此之外ObjectFactory就是一個普通的接口
簡單來說就是通過FactoryBean你可以控制對象如何創(chuàng)建,而ObjectFactory借助Scope接口自定義scope你可以控制對象的創(chuàng)建時機也可以用來延遲初始化來解決循環(huán)依賴問題。
參考
補充介紹spring中關于FactoryBean 和 ObjectFactory的認識和區(qū)別
FactoryBean:
這個接口使你可以提供一個復雜的邏輯來生成 Bean。它本質(zhì)是一個 Bean,但這個 Bean 不是用來注 入到其它地方像 Service、Dao 一樣使用的,它是用來生成其它 Bean 使用的。實現(xiàn)了這個接口后, Spring 在容器初始化時,把實現(xiàn)這個接口的 Bean 取出來,使用接口的 getObject()方法來生成我們 要想的 Bean。當然,那些生成 Bean 的業(yè)務邏輯也要寫 getObject()方法中。 其返回的對象不是指定類的一個實例,其返回的是該工廠 Bean 的 getObject 方法所返回的對象。創(chuàng) 建出來的對象是否屬于單例由 isSingleton 中的返回決定。
使用場景:
1、通過外部對類是否是單例進行控制,該類自己無法感知
2、在創(chuàng)建 Object 對象之前進 行初始化的操作,在 afterPropertiesSet()中完成。(一次性的初始化,保存在成員變量中,并不是 每次 getObject 都會調(diào)用 afterPropertiesSet,afterPropertiesSet 只會被調(diào)用一次)
ObjectFactory:
它的目的也是作為一個工廠,來生成 Object(這個接口只有一個方法 getObject())。這個接口一般被 用來,包裝一個 factory,通過個這工廠來返回一個新實例(prototype 類型)。這個接口和 FactoryBean 有點像,但 FactoryBean 的實現(xiàn)是被當做一個 SPI(Service Provider Interface)實例來使用在 BeanFactory 里面;ObjectFactory 的實現(xiàn)一般被用來注入到其它 Bean 中,作為 API 來使用。就像ObjectFactoryCreatingFactoryBean 的 例 子 , 它 的 返 回 值 就 是 一 個 ObjectFactory , 這 個 ObjectFactory 被注入到了 Bean 中,在 Bean 通過這個接口的實例,來取得我們想要的 Bean。
總的來說,F(xiàn)actoryBean 和 ObjectFactory 都是用來取得 Bean,但使用的方法和地方不同, FactoryBean 被配置好后,Spring 調(diào)用 getObject()方法來取得 Bean,ObjectFactory 配置好后, 在 Bean 里面可以取得 ObjectFactory 實例,需要我們手動來調(diào)用 getObject()來取得 Bean。
到此這篇關于Spring中BeanFactory FactoryBean和ObjectFactory的三種的區(qū)別的文章就介紹到這了,更多相關BeanFactory FactoryBean和ObjectFactory區(qū)別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java微信公眾平臺開發(fā)(2) 微信服務器post消息體的接收
這篇文章主要為大家詳細介紹了Java微信公眾平臺開發(fā)第二步,微信服務器post消息體的接收,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-04-04Java實現(xiàn)作業(yè)調(diào)度的示例代碼
這篇文章主要為大家詳細介紹了如何利用Java實現(xiàn)SJF算法調(diào)度,要求測試數(shù)據(jù)可以隨即輸入或從文件中讀入,文中的示例代碼講解詳細,需要的可以參考一下2023-04-04SpringBoot使用@valid進行參數(shù)校驗的流程步驟
SpringBoot 提供了一種方便的方式來進行參數(shù)校驗:使用 Hibernate Validator,Spring Boot 提供了一種方便的方式來進行參數(shù)校驗:使用 Hibernate Validator,所以本文給大家介紹了SpringBoot使用@valid進行參數(shù)校驗的流程步驟,需要的朋友可以參考下2023-09-09java 刪除文件夾中的所有內(nèi)容而不刪除文件夾本身的實例
下面小編就為大家?guī)硪黄猨ava 刪除文件夾中的所有內(nèi)容而不刪除文件夾本身的實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-12-12java操作mongodb之多表聯(lián)查的實現(xiàn)($lookup)
這篇文章主要介紹了java操作mongodb之多表聯(lián)查的實現(xiàn)($lookup),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-03-03java使用compareTo實現(xiàn)一個類的對象之間比較大小操作
這篇文章主要介紹了java使用compareTo實現(xiàn)一個類的對象之間比較大小操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09