所以我有這個非常奇怪和令人不安的問題。在我們的低性能計算機上,我們的一些singleton bean在Spring Context初始化期間被複制。這隻發生在硬件性能低下的計算機上,並且一直髮生。低性能計算機上的Spring bean singleton複製
到目前爲止,我所知道的是它似乎正發生在一堆循環依賴的類中,我懷疑它可能與bean init方法有關。通過init方法而不是構造函數將LockScreen注入到MainContentPane中來解決循環依賴問題。
我有兩個日誌,一個來自正常的性能計算機,另一個來自低性能計算機。日誌顯示了差異和問題。行尾的數字是來自方法System.identityHashCode(object)的實例ID。日誌格式爲:
LOGLEVEL [Thread ID] LoggingClass Message
在正常的性能計算機上發生以下打印輸出。
INFO [JavaFX Application Thread] MainContentPane Constructor: 869589588
INFO [JavaFX Application Thread] MainContentPane Getting LockScreen In Spring Init....
INFO [JavaFX Application Thread] SessionHandler Constructor: 939274676
INFO [JavaFX Application Thread] SessionHandler Injected MainContentPane Instance: 869589588
INFO [JavaFX Application Thread] UserStateBinder Constructor: 2010765576
INFO [JavaFX Application Thread] UserStateBinder Injected SessionHandler Instance: 939274676
INFO [JavaFX Application Thread] LockScreenLockedController Constructor: 1866179042
INFO [JavaFX Application Thread] LockScreenLockedController Injected UserStateBinder Instance: 2010765576
INFO [JavaFX Application Thread] LockScreen Constructor: 204176749
INFO [JavaFX Application Thread] LockScreen Injected LockScreenLockedController Instance: 1866179042
INFO [JavaFX Application Thread] LockScreen This instance: 204176749
INFO [JavaFX Application Thread] LockScreen Bean Factory instance: 1371189401
INFO [JavaFX Application Thread] MainContentPane Injected LockScreen Instance: 204176749
這裏沒有重複。
但是,如果我們查看低性能計算機的日誌,我們可以看到在初始化之後創建了與上述類似的重複項。
INFO [JavaFX Application Thread] MainContentPane Constructor: 22324067
INFO [JavaFX Application Thread] MainContentPane Getting LockScreen In Spring Init....
INFO [JavaFX Application Thread] SessionHandler Constructor: 32463502
INFO [JavaFX Application Thread] SessionHandler Injected MainContentPane Instance: 22324067
INFO [JavaFX Application Thread] UserStateBinder Constructor: 19793387
INFO [JavaFX Application Thread] UserStateBinder Injected SessionHandler Instance: 32463502
INFO [JavaFX Application Thread] LockScreenLockedController Constructor: 29065840
INFO [JavaFX Application Thread] LockScreenLockedController Injected UserStateBinder Instance: 19793387
INFO [JavaFX Application Thread] LockScreen Constructor: 12729388
INFO [JavaFX Application Thread] LockScreen Injected LockScreenLockedController Instance: 29065840
INFO [JavaFX Application Thread] LockScreen This instance: 12729388
INFO [JavaFX Application Thread] LockScreen Bean Factory instance: 30716643
INFO [JavaFX Application Thread] MainContentPane Injected LockScreen Instance: 12729388
INFO [JavaFX Application Thread] SessionHandler Constructor: 11043228
INFO [JavaFX Application Thread] SessionHandler Injected MainContentPane Instance: 22324067
INFO [JavaFX Application Thread] UserStateBinder Constructor: 24902967
INFO [JavaFX Application Thread] UserStateBinder Injected SessionHandler Instance: 32463502
INFO [JavaFX Application Thread] LockScreenLockedController Constructor: 17521714
INFO [JavaFX Application Thread] LockScreenLockedController Injected UserStateBinder Instance: 19793387
INFO [JavaFX Application Thread] LockScreen Constructor: 16791356
INFO [JavaFX Application Thread] LockScreen Injected LockScreenLockedController Instance: 29065840
INFO [JavaFX Application Thread] LockScreen This instance: 16791356
INFO [JavaFX Application Thread] LockScreen Bean Factory instance: 30716643
在這裏我們可以看到,有一個第二組除MainContentPane類的所有類創建的實例。新的一組類是依賴注入前一組實例(檢查id),並且bean工廠與以前是相同的實例。
所有這些消息都印在主線程(JavaFX Application Thread)上,所以似乎也沒有併發問題。
該項目還包括一個嵌入式Jetty http服務器。我不知道在Jetty中是否有可能導致低性能計算機出現此問題的問題。
版本:
JRE(incl. JavaFX): 1.8.0.101
Spring: 4.3.3.RELEASE
Jetty + Websocket: 9.3.6.v20151106
我懷疑這個問題可能已經通過設置Spring上下文設置setAllowBeanDefinitionOverriding(假)解決。但那也沒有幫助。
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.setAllowBeanDefinitionOverriding(false);
context.register(ClientContext.class,
MainContext.class,
CommonContext.class,
CciContext.class,
PersistenceContext.class,
SimulatorContext.class);
context.refresh();
請告訴我,如果有任何額外的信息,你需要,並感謝您在任何時候你幫助我。
編輯:
我現在已經證實,所有動初始化,所有的bean的訪問是由一個單獨的線程發生。 我只能在跟蹤日誌中找到兩個有趣的事實。首先,似乎所有的啓動都是以相同的順序發生的,即使它是完全相同的軟件版本(Spring是在paralell中初始化的嗎?)。 二,中等性能的電腦確實有重複!它們只在UserStateBinder類中有重複(或者可能是重新初始化?)。高性能的開發電腦完全沒有這個問題。
我們可能會從明天開始將項目從我們的項目中刪除,因爲我們一直無法找到解決此問題的解決方案。如果其他人希望我測試任何理論,我仍然可以使用當前版本的項目。
那麼,當它在'MainContentPane'中設置'LockScreen'時,會發生循環bean引用?每臺計算機上的JVM版本是否相同? – Asoub
循環引用是: LockScreen - > LockScreenLockedController - > UserStateBinder - > SessionHandler - > MainContentPane - > LockScreen,它通過讓MainContentPane獲取LockScreen bean的Spring init方法而不是它的構造函數來解決。關於JVM,是的,在所有的計算機上都是一樣的。 JRE與應用程序捆綁在一起以確保它。 – Flipbed
這聽起來很晦澀。你可以在你慢速的慢電腦上試試debbugger(如果可能,用eclipse)? – Asoub