【Spring源碼】 FactoryBean接口

容器初始化階段 實例化原始bean

啟動容器的時候,如果當(dāng)前bean 實現(xiàn)了FactoryBean,則先實例化將name改成(&original),beanName=original,將BD.isFactoryBean改為true,先實例化的也是原生bean,單例池存的就是
{original(beanName),@Original(原實例)},

先給name加個前綴 &

image

beanName會去除&,但是name還是&開頭的

image

先實例化原始bean,beanName作為一級緩存的key

image

最后嘗試替換成getObject,但是發(fā)現(xiàn)是&符號開頭,且為FactoryBean類型,則不調(diào)用getObject方法,返回原始實例

image

如果手動調(diào)用getBean("&original"),和上面的流程是一樣的,只不過可能是從緩存中先取出原始bean

getBean("original")

getObject的實例在啟動階段不會被實例化,必須得等到getBean("original")的時候再實例化,
SmartFactoryBean 如果實現(xiàn)的是這個接口,并且重寫的isEagerInit()返回的是true,提前觸發(fā)getObject

image

根據(jù)原始bean的beanName,先從緩存中取出原實例(原實例在容器初始化階段就已實例化)

image

如果name 是 & 開頭的,則返回原實例

image

是否是FactoryBean類型,不是的話直接返回

image

是的話往下走, 先FactoryBean的緩存factoryBeanObjectCache中拿getObject()返回的bean,拿不到調(diào)用原實例的getObject

image

調(diào)用原實例的getObject

image
image

最后加入把替換成getObject()返回實例 加入factoryBeanObjectCache緩存中

image

總結(jié):

  1. 實現(xiàn)FactoryBean接口的bean會創(chuàng)建兩個對象,一個是原始bean,一個是FactoryBean的getObject()返回的bean
  2. 原始bean在容器refresh的階段就會創(chuàng)建,并且會放入一級緩存中,key為無&的名稱,由于這個階段在容器調(diào)用getBean的時候,會由于它是FactoryBean類型,給他的name加上&,所以實例化后的替換階段會直接返回原實例,不會觸發(fā)getObject
  3. 觸發(fā)getObject一般不會在refresh階段,需要你手動調(diào)用getBean("原始bean名稱"),除非你實現(xiàn)SmartFactoryBean接口,并且重寫isEagerInit()返回true
  4. 觸發(fā)getObject()會返回一個新對象,并且有一個專門存放這種bean的緩存factoryBeanObjectCache,{原始bean名稱 :getObject返回的實例}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容