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

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

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

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

如果手動調(diào)用getBean("&original"),和上面的流程是一樣的,只不過可能是從緩存中先取出原始bean
getBean("original")
getObject的實例在啟動階段不會被實例化,必須得等到getBean("original")的時候再實例化,
SmartFactoryBean 如果實現(xiàn)的是這個接口,并且重寫的isEagerInit()返回的是true,提前觸發(fā)getObject

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

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

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

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

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


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

總結(jié):
- 實現(xiàn)FactoryBean接口的bean會創(chuàng)建兩個對象,一個是原始bean,一個是FactoryBean的getObject()返回的bean
- 原始bean在容器refresh的階段就會創(chuàng)建,并且會放入一級緩存中,key為無&的名稱,由于這個階段在容器調(diào)用getBean的時候,會由于它是FactoryBean類型,給他的name加上&,所以實例化后的替換階段會直接返回原實例,不會觸發(fā)getObject
- 觸發(fā)getObject一般不會在refresh階段,需要你手動調(diào)用getBean("原始bean名稱"),除非你實現(xiàn)SmartFactoryBean接口,并且重寫isEagerInit()返回true
- 觸發(fā)getObject()會返回一個新對象,并且有一個專門存放這種bean的緩存factoryBeanObjectCache,{原始bean名稱 :getObject返回的實例}