熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java開源技術 >> 正文

Spring Singleton的陷阱介紹

2022-06-13   來源: Java開源技術 

  這是一個真實的案例我們在項目中使用Spring和ACEGI我之所以選擇ACEGI除了它對權限的良好控制外

  我還看好它的SecurityContextHolder通過代碼 Authentication auth = SecurityContextHoldergetContext()getAuthentication()

  我可以很容易在系統任意一層得到用戶的信息而不用把用戶信息在參數裡傳來傳去(這也是struts的缺點之一)

  但是我在每一次要得到用戶信息的時候都寫上面的一段代碼未免有些麻煩所以我在BaseService BaseDao裡都提供了如下方法 /**//**

  * get current login user info

  * @return UserInfo

  */

  protected UserInfo getUserInfo()

  ……{

  return getUserContext()getUserInfo()

  }

  /**//**

  * get current login user context

  * @return UserContext

  */

  protected UserContext getUserContext()

  ……{

  Authentication auth = SecurityContextHoldergetContext()getAuthentication()

  return (UserContext) authgetPrincipal()

  }

  這樣在其他的Service和Dao類裡可以通過 supergetUserContext() supergetUserInfo()

  來得到用戶的信息這也為問題的產生提供了溫床請看如下代碼 public class SomeServece extends BaseService implements SomeInterFace

  ……{

  private UserInfo user = supergetUserInfo()

  public someMethod()

  ……{

  int userID = thisusergetUserID()

  String userName = thisusergetUserName()

  //bla bla do something user userID and userNaem

  }

  }

  這段代碼在單元測試的時候不會用任何問題但是在多用戶測試的情況下你會發現任何調用SomeService裡someMethod()方法的userID和userName都是同一個人也就是第一個登陸的人的信息Why?

  其根本原因是Spring的Bean在默認情況下是Singleton的Bean SomeServece的實例只會生成一份也就是所SomeServece實例的user 對象只會被初始化一次就是第一次登陸人的信息以後不會變了所以BaseService想為開發提供方便確給開發帶來了風險正確的用法應該是這樣的 public class SomeServece extends BaseService implements SomeInterFace

  ……{

  public someMethod()

  ……{

  int userID = supergetUserInfo()getUserID()

  String userName = supergetUserInfo()getUserName()

  //bla bla do something user userID and userNaem

  }

  }


From:http://tw.wingwit.com/Article/program/Java/ky/201311/28799.html
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.