Spring中BeanFactory?FactoryBean和ObjectFactory的三種的區(qū)別
Spring中BeanFactory FactoryBean和ObjectFactory的三種的區(qū)別
引言
關(guān)于FactoryBean 和 BeanFactory的對比文章比較多,但是對ObjectFactory的描述就比較少,今天我們對比下這三種的區(qū)別。
結(jié)論
BeanFactory就是對象工廠,Spring的底層容器,用于實例化和保存對象。
FactoryBean是一個工廠對象,用于實例化創(chuàng)建過程比較復(fù)雜的對象,對象的創(chuàng)建過程是由用戶自己控制的。
ObjectFactory是某個特定的工廠,用于在項目啟動時,延遲實例化對象,解決循環(huán)依賴問題,也就是三級緩存那里會用到,以及結(jié)合Scope,靈活方便的實現(xiàn)是否需要創(chuàng)建對象。
BeanFactory
Spring最最核心的接口,Bean工廠,從名字上就能看出這是一個工廠。它是Spring最底層的容器,負責(zé)實例化和保存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接口的類,負責(zé)返回這個java類的實例化對象。
從設(shè)計模式的角度來看這就是典型的工廠方法模式。由一個特定的工廠來生產(chǎn)特定的java類的實例化對象。
那么這種寫法有哪些好處呢?
正常情況下,Spring中在實例化對象的時候,都是由BeanFactory從上下文中獲取BeanDefinition信息,然后通過反射,調(diào)用這個java類的構(gòu)造方法進行實例化。而現(xiàn)在這種形式,我們相當于將實例化的功能交給了FactoryBean去實現(xiàn)。這種方式主要使用在一些比較復(fù)雜的實例化過程中,并非簡單地設(shè)置一些參數(shù)或者設(shè)置的參數(shù)過多,過程中可能需要做一些復(fù)雜的解析、判斷和邏輯處理,這個時候交由Spring去通過反射進行實例化可能就不太靈活了,
Spring容器中有兩種Bean,一種是普通的Bean對象,一種是實現(xiàn)了FactoryBean的工廠Bean對象。如果從BeanFactory中g(shù)etBean的時候,獲取到的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中關(guān)于FactoryBean 和 ObjectFactory的認識和區(qū)別
FactoryBean:
這個接口使你可以提供一個復(fù)雜的邏輯來生成 Bean。它本質(zhì)是一個 Bean,但這個 Bean 不是用來注 入到其它地方像 Service、Dao 一樣使用的,它是用來生成其它 Bean 使用的。實現(xiàn)了這個接口后, Spring 在容器初始化時,把實現(xiàn)這個接口的 Bean 取出來,使用接口的 getObject()方法來生成我們 要想的 Bean。當然,那些生成 Bean 的業(yè)務(wù)邏輯也要寫 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。
到此這篇關(guān)于Spring中BeanFactory FactoryBean和ObjectFactory的三種的區(qū)別的文章就介紹到這了,更多相關(guān)BeanFactory FactoryBean和ObjectFactory區(qū)別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot 設(shè)置局域網(wǎng)訪問的實現(xiàn)步驟
Spring Boot是一個開源Java-based框架,用于創(chuàng)建獨立的、生產(chǎn)級別的Spring應(yīng)用,它旨在簡化Spring應(yīng)用的初始搭建及開發(fā)過程,通過提供各種自動配置的starter包,Spring Boot使得項目配置變得簡單快速,感興趣的朋友一起看看吧2024-02-02
Spring Boot + Vue 前后端分離項目如何踢掉已登錄用戶
這篇文章主要介紹了Spring Boot + Vue 前后端分離項目如何踢掉已登錄用戶,需要的朋友可以參考下2020-05-05
Eclipse 導(dǎo)出可執(zhí)行Java工程/可執(zhí)行Jar文件(包含第三方Jar包)
這篇文章主要介紹了Eclipse 導(dǎo)出可執(zhí)行Java工程/可執(zhí)行Jar文件(包含第三方Jar包)的相關(guān)資料,需要的朋友可以參考下2016-11-11
深入分析:用1K內(nèi)存實現(xiàn)高效I/O的RandomAccessFile類的詳解
本篇文章是對用1K內(nèi)存實現(xiàn)高效I/O的RandomAccessFile類的詳細分析介紹,需要的朋友參考下2013-05-05
在Java中String和Date、Timestamp之間的轉(zhuǎn)換
這篇文章主要介紹了在Java中String和Date、Timestamp之間的轉(zhuǎn)換 的相關(guān)資料,需要的朋友可以參考下2015-12-12
Java將RTF轉(zhuǎn)換為PDF格式的實現(xiàn)
本文主要介紹了Java將RTF轉(zhuǎn)換為PDF格式的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07

