Spring.net 的一个bug ?

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

     我配置了GameRoomConfig对象:

 

复制代码
 <object name="gameRoomConfig" type="GamePlatform.Entity.Runtime.GameRoomConfig,GamePlatform.Entity">
        
<property name="ID" value="3011"/>
        
<property name="GameID" value="DDZ"/>
        
<property name="ListenIP" value="192.168.0.206"/>
        
<property name="ListenPort" value="9090"/>
        
<property name="IP" value="192.168.0.206"/>
        
<property name="Port" value="9090"/>
        
<property name="MaxUserCount" value="500"/>
        
<property name="GPSCallback" ref="serviceForGPSCallback"/>
      
</object>
复制代码

 

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

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

<object name="gameRoomConfig" type="GamePlatform.Entity.Runtime.GameRoomConfig,GamePlatform.Entity" singleton="false" >

     

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

 

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

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

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

 

复制代码
    public class GameInitializer
    {  
        
#region GameRoomConfig
        
private GameRoomConfig gameRoomConfig;
        
public GameRoomConfig GameRoomConfig
        {
            
set { gameRoomConfig = value; }
        } 
        
#endregion             

        
#region GPSCallback
        
private IGPSCallback gPSCallback;
        
public IGPSCallback GPSCallback
        {
            
set { gPSCallback = value; }
        } 
        
#endregion

        
public void Initialize()
        {
            
/* 由于GPSCallback对象引入了循环依赖,斩断它 */
            
this.gameRoomConfig.GPSCallback = this.gPSCallback;         
        }
    }
复制代码

     

 

 

posted @   zhuweisky  阅读(2377)  评论(1编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述
点击右上角即可分享
微信分享提示