本來是在debug dubbo的reference bean的init()過程,因?yàn)镽eferenceBean是繼承了Spring FactoryBean接口的,
所以初始化入口自然就是FactoryBean定義的函數(shù),getObject()。在該方法內(nèi),只顯示調(diào)用了ReferenceConfig.get()。
內(nèi)容如下:
public synchronized
可以看到,核心的初始化代碼就在init()中。這里,會(huì)首先判斷factoryBean 要?jiǎng)?chuàng)建的bean實(shí)例ref是否已經(jīng)初始化,若未初始化,才會(huì)進(jìn)行Init()調(diào)用。
所以,我斷點(diǎn)自然就打在ReferenceBean.getObject()上。
啟動(dòng)spring。
反復(fù)多次,我發(fā)現(xiàn),只要我在ReferenceBean.getObject()或者ReferenceConfig.get()上加上斷點(diǎn),ref實(shí)例就會(huì)莫名其妙地已經(jīng)被初始化過,proxy$xxxx。
這就奇怪了。
這個(gè)ReferenceBean的整個(gè)的入口函數(shù),getObject()的觸發(fā),是在我的控制下的啊,即:
springContext.getBean("referenceBeanId");
那我就在想,是不是spring container的初始化有異步的部分呢?所以我就直接把斷點(diǎn)加載init()方法上。
然后我返回調(diào)試后發(fā)現(xiàn),如果我只將斷點(diǎn)加在Init(),而ReferenceBean.getObject()與ReferenceConfig.get()不加斷點(diǎn)的話,init()方法里是正常進(jìn)入,且進(jìn)入的代碼initialized也是false的
private void
}
<pre style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 1em; margin-top: 5px; margin-bottom: 5px; overflow: visible;">就是init()開頭4行代碼處。</pre>
<pre style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 1em; margin-top: 5px; margin-bottom: 5px; overflow: visible;">后來我就想,是不是哪里給反射注入了呢?當(dāng)然,我也沒啥發(fā)現(xiàn),我就直接百度了。結(jié)果果不其然。</pre>
<pre style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 1em; margin-top: 5px; margin-bottom: 5px; overflow: visible;">在網(wǎng)上發(fā)現(xiàn)了一篇同樣問的文章。那個(gè)人在源碼里加了一段注釋,如下</pre>
圖片已損壞
圖片已損壞
可以看到,AbstractConfig.toString()方法竟然反射調(diào)用了ReferenceConfig.init()方法。。。
AbstractConfig.toString()的代碼如下:

可以看到,這個(gè)if里是對(duì)所有g(shù)etter通過的,通過后,又再接下來的紅框處調(diào)用了我擦,也就是說,ReferenceBean.getObject()給調(diào)用了,進(jìn)而也就init()給調(diào)用了。
后來,原文作者又做了這樣一個(gè)測(cè)試,得出了最終結(jié)果
圖片已損壞
結(jié)果就是:
IDEA這類編輯器的debug功能為了在斷點(diǎn)處能夠顯示類實(shí)例的相關(guān)信息,就會(huì)反射調(diào)用相關(guān)類實(shí)例的toString()方法?。。?!
思考:
DUBBO為什么要在AbstractConfig.toString()的反射調(diào)用init()呢?真尼瑪奇怪。。。。
答案:
dubbo的AbstractConfig的toString方法反射調(diào)用只是為了輸出時(shí)能夠更全面一點(diǎn)。但是因?yàn)锳bstractConfig的子類
ReferenceBean實(shí)現(xiàn)了FactoryBean接口,這個(gè)接口是Spring用來獲取Bean實(shí)例的工廠bean,生成bean的方法就叫g(shù)etObject,正好符合了toString里面邏輯,而getObject里是要初始化bean的。所以,就這么巧地對(duì)應(yīng)上了