原本是在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的。因此,就这么巧地对应上了