Spring.net 的一个bug ?

解决Spring.NET循环依赖
本文描述了一个关于Spring.NET IOC容器中出现的奇怪bug,即配置的GameRoomConfig对象在依赖对象初始化时未被正确设置。经过排查发现是由于复杂的依赖关系中存在循环依赖导致。文章给出了通过移除特定依赖及引入Bridge对象来解决该问题的方法。

我在项目中都使用Spring.net作为IOC容器,今天有遇到了以前曾经出现的一个奇怪的bug,描述如下。

我配置了GameRoomConfig对象:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><objectname="gameRoomConfig"type="GamePlatform.Entity.Runtime.GameRoomConfig,GamePlatform.Entity">
<propertyname="ID"value="3011"/>
<propertyname="GameID"value="DDZ"/>
<propertyname="ListenIP"value="192.168.0.206"/>
<propertyname="ListenPort"value="9090"/>
<propertyname="IP"value="192.168.0.206"/>
<propertyname="Port"value="9090"/>
<propertyname="MaxUserCount"value="500"/>
<propertyname="GPSCallback"ref="serviceForGPSCallback"/>
</object>

在IOC容器中,有多个对象都注入了配置的这个gameRoomConfig对象,而这些配置在以前一年多的时间中一直工作良好,今天我重装系统后,再在VS中启动这个程序就无法正常运行了,原因在于其它依赖于gameRoomConfig的对象在它们自己的Initialize方法中使用gameRoomConfig时候,gameRoomConfig的各个属性还未被赋值。也就是说,gameRoomConfig对象还未被正确设置就被其它依赖对象使用了。我为其它依赖对象加上 depends-on="gameRoomConfig" 来作强制检查也于事无补。

真是奇怪,在一年多以前就遇到过这个问题,后来不知道是什么原因又莫名其妙的自动好了,现在又出现了。当前我的补救方案是,将gameRoomConfig对象由Singleton模式改为SingleCall模式,这样每个依赖对象都使用一个独立的gameRoomConfig对象了。

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><objectname="gameRoomConfig"type="GamePlatform.Entity.Runtime.GameRoomConfig,GamePlatform.Entity"singleton="false">

如果大家也有遇到过类似的问题,请告知一下真正的原因,谢谢。

正解:应该是在错综复杂的依赖关系中引入了循环依赖,我通过移除一个属性依赖,使得系统又恢复正常。上面所述的现象看似问题出在gameRoomConfig对象上,实则不然,我斩断的那个循环依赖链似乎与gameRoomConfig对象的关联不大。

也就是说,如果依赖关系中出现循环依赖,则会导致循环链中的某个对象在其属性未被赋值前就被其它依赖对象所使用。

解决的方案是,斩断循环依赖,这可以通过引入一个中间的Bridge对象做到,在Bridge对象的Initialize方法中,将两者的依赖关系动态的建立起来(这就绕过了Spring的对象依赖的静态检测)。如桥的Initialize方法示例:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->publicclassGameInitializer
{
#regionGameRoomConfig
privateGameRoomConfiggameRoomConfig;
publicGameRoomConfigGameRoomConfig
{
set{gameRoomConfig=value;}
}
#endregion

#regionGPSCallback
privateIGPSCallbackgPSCallback;
publicIGPSCallbackGPSCallback
{
set{gPSCallback=value;}
}
#endregion

publicvoidInitialize()
{
/*由于GPSCallback对象引入了循环依赖,斩断它*/
this.gameRoomConfig.GPSCallback=this.gPSCallback;
}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值