dubbo debug過程中發現的IDEA有趣的小發現及dubbo消費者debug小tips

秋褲Boy發表於2019-01-21

本來是在debug dubbo的reference bean的init()過程,因為ReferenceBean是繼承了Spring FactoryBean介面的,

所以初始化入口自然就是FactoryBean定義的函式,getObject()。在該方法內,只顯示呼叫了ReferenceConfig.get()。

內容如下:

public synchronized 
複製程式碼

可以看到,核心的初始化程式碼就在init()中。這裡,會首先判斷factoryBean 要建立的bean例項ref是否已經初始化,若未初始化,才會進行Init()呼叫。

所以,我斷點自然就打在ReferenceBean.getObject()上。

啟動spring。

反覆多次,我發現,只要我在ReferenceBean.getObject()或者ReferenceConfig.get()上加上斷點,ref例項就會莫名其妙地已經被初始化過,proxy$xxxx。

這就奇怪了。

這個ReferenceBean的整個的入口函式,getObject()的觸發,是在我的控制下的啊,即:

springContext.getBean("referenceBeanId");

那我就在想,是不是spring container的初始化有非同步的部分呢?所以我就直接把斷點載入init()方法上。

然後我返回撥試後發現,如果我只將斷點加在Init(),而ReferenceBean.getObject()與ReferenceConfig.get()不加斷點的話,init()方法裡是正常進入,且進入的程式碼initialized也是false的

private void 
複製程式碼
}
複製程式碼
就是init()開頭4行程式碼處。
後來我就想,是不是哪裡給反射注入了呢?當然,我也沒啥發現,我就直接百度了。結果果不其然。
在網上發現了一篇同樣問的文章。那個人在原始碼里加了一段註釋,如下

圖片已損壞

圖片已損壞

可以看到,AbstractConfig.toString()方法竟然反射呼叫了ReferenceConfig.init()方法。。。

AbstractConfig.toString()的程式碼如下:

image

可以看到,這個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的。所以,就這麼巧地對應上了

相關文章