原本是在debug dubbo的reference bean的init()過程,由於ReferenceBean是繼承了Spring FactoryBean接口的,spring
因此初始化入口天然就是FactoryBean定義的函數,getObject()。在該方法內,只顯示調用了ReferenceConfig.get()。bash
內容以下:異步
public synchronized
複製代碼
能夠看到,核心的初始化代碼就在init()中。這裏,會首先判斷factoryBean 要建立的bean實例ref是否已經初始化,若未初始化,纔會進行Init()調用。編輯器
因此,我斷點天然就打在ReferenceBean.getObject()上。函數
啓動spring。測試
反覆屢次,我發現,只要我在ReferenceBean.getObject()或者ReferenceConfig.get()上加上斷點,ref實例就會莫名其妙地已經被初始化過,proxy$xxxx。spa
這就奇怪了。debug
這個ReferenceBean的整個的入口函數,getObject()的觸發,是在個人控制下的啊,即:調試
springContext.getBean("referenceBeanId");
code
那我就在想,是否是spring container的初始化有異步的部分呢?因此我就直接把斷點加載init()方法上。
而後我返回調試後發現,若是我只將斷點加在Init(),而ReferenceBean.getObject()與ReferenceConfig.get()不加斷點的話,init()方法裏是正常進入,且進入的代碼initialized也是false的
private void
複製代碼
}
複製代碼
就是init()開頭4行代碼處。
後來我就想,是否是哪裏給反射注入了呢?固然,我也沒啥發現,我就直接百度了。結果果不其然。
在網上發現了一篇一樣問的文章。那我的在源碼里加了一段註釋,以下
圖片已損壞
圖片已損壞
能夠看到,AbstractConfig.toString()方法居然反射調用了ReferenceConfig.init()方法。。。
AbstractConfig.toString()的代碼以下:
能夠看到,這個if裏是對全部getter經過的,經過後,又再接下來的紅框處調用了我擦,也就是說,ReferenceBean.getObject()給調用了,進而也就init()給調用了。
後來,原文做者又作了這樣一個測試,得出了最終結果
圖片已損壞
IDEA這類編輯器的debug功能爲了在斷點處可以顯示類實例的相關信息,就會反射調用相關類實例的toString()方法!!!!
DUBBO爲何要在AbstractConfig.toString()的反射調用init()呢?真尼瑪奇怪。。。。
dubbo的AbstractConfig的toString方法反射調用只是爲了輸出時可以更全面一點。可是由於AbstractConfig的子類
ReferenceBean實現了FactoryBean接口,這個接口是Spring用來獲取Bean實例的工廠bean,生成bean的方法就叫getObject,正好符合了toString裏面邏輯,而getObject裏是要初始化bean的。因此,就這麼巧地對應上了