--Spring的singleton是容器級的,我們一般說的singleton模式是JVM級的。所以singleton模式中,singleton的class在整個JVM中只有一個instance,Spring的Bean,你可以一個class配置多個Bean,這個class就有了多個instance。這個singleton是指在spring容器中,這個Bean是單實例的,是線程共享的。所以要求這些類都是線程安全的。也就是說,不能出現修改Bean屬性的方法,當然除了設值得那些setter。只要滿足線程安全,這些bean都可以用singleton。而且我們在絕大多數使用上,也是這樣用的,包括dao,service。
Beanfactory是Spring初始以靜態方式載入的,Spring的單例IOC是基于容器級的,所以這你都不用擔心與考慮.
--應用中對象有兩種,行為對象和數據對象,行為對象都要求是線程安全的!也就是允許單例的, 不管是dao 還是 service 對象,都是行為對象,行為對象不應該引用非線程安全的對象做成員量,同時在應用外部的資源(如文件,數據庫連接,session)時,要先保證對這些東西的訪問是做了并發控制的!
對于spring來講,<bean scope="singleton"/>或<bean singleton="true"/>都是保證對同一sesionfactory bean是單例的,也就是所謂 sessionfactory 范圍的.
--這是一個真實的案例,我們在項目中使用Spring和ACEGI,我之所以選擇ACEGI,除了它對權限的良好控制外,
我還看好它的SecurityContextHolder,通過代碼
代碼
- Authentication auth = SecurityContextHolder.getContext().getAuthentication();
<script>render_code();</script>
我可以很容易在系統任意一層得到用戶的信息,而不用把用戶信息在參數里傳來傳去,(這也是struts的缺點之一)
但是我在每一次要得到用戶信息的時候都寫上面的一段代碼,未免有些麻煩,所以我在BaseService, BaseDao里都提供了如下方法:
代碼
-
-
-
-
- protected UserInfo getUserInfo()
- {
- return getUserContext().getUserInfo();
- }
-
-
-
-
-
- protected UserContext getUserContext()
- {
- Authentication auth = SecurityContextHolder.getContext().getAuthentication();
- return (UserContext) auth.getPrincipal();
- }
<script>render_code();</script>
這樣在其他的Service和Dao類里可以通過
代碼
- super.getUserContext(), super.getUserInfo()
<script>render_code();</script>
來得到用戶的信息,這也為問題的產生提供了溫床。請看如下代碼:
代碼
- public class SomeServece extends BaseService implements SomeInterFace
- {
- private UserInfo user = super.getUserInfo();
-
- public someMethod()
- {
- int userID = this.user.getUserID();
- String userName = this.user.getUserName();
-
- }
- }
<script>render_code();</script>
這段代碼在單元測試的時候不會用任何問題,但是在多用戶測試的情況下,你會發現任何調用SomeService里someMethod()方法
的userID和userName都是同一個人,也就是第一個登陸的人的信息。Why?
其根本原因是Spring的Bean在默認情況下是Singleton的,Bean SomeServece的實例只會生成一份,也就是所SomeServece實例的user
對象只會被初始化一次,就是第一次登陸人的信息,以后不會變了。所以BaseService想為開發提供方便,卻給開發帶來了風險
正確的用法應該是這樣的
代碼
- public class SomeServece extends BaseService implements SomeInterFace
- {
-
-
- public someMethod()
- {
- int userID = super.getUserInfo().getUserID();
- String userName = super.getUserInfo().getUserName();
-
- }
posted on 2009-04-08 12:12
Sun River 閱讀(755)
評論(0) 編輯 收藏 所屬分類:
Spring