Spring Bean Scope 有狀態的Bean和無狀態的Bean

weixin_33766168發表於2017-06-28
 在Spring的Bean配置中,存在這樣兩種情況:
    <bean id="testManager" class="com.sw.TestManagerImpl" scope="singleton" />  
      
     <bean id="testManager" class="com.sw.TestManagerImpl" scope="prototype" />  

當然,scope的值不止這兩種,還包括了request,session 等。但用的最多的還是singleton單態,prototype多型。

singleton表示該bean全域性只有一個例項,Spring中bean的scope預設也是singleton.

prototype表示該bean在每次被注入的時候,都要重新建立一個例項,這種情況適用於有狀態的Bean.

對於SSH架構的系統,很少關心這方面,因為我們用到的一般都是singleton. Bean的注入由Spring管理。

對於有狀態的Bean呢?

下面是一個有狀態的Bean

    package com.sw;  
      
    public class TestManagerImpl implements TestManager{  
        private User user;    
      
        public void deleteUser(User e) throws Exception {  
            user = e ;           //1  
            prepareData(e);  
        }  
      
        public void prepareData(User e) throws Exception {  
            user = getUserByID(e.getId());            //2  
            .....  
            //使用user.getId();                       //3  
            .....  
            .....  
        }     
    }  

如果該Bean配置為singleton,會出現什麼樣的狀況呢?

如果有2個使用者訪問,都呼叫到了該Bean.

假定為user1,user2

當user1 呼叫到程式中的1步驟的時候,該Bean的私有變數user被付值為user1

當user1的程式走到2步驟的時候,該Bean的私有變數user被重新付值為user1_create

理想的狀況,當user1走到3步驟的時候,私有變數user應該為user1_create;

但如果在user1呼叫到3步驟之前,user2開始執行到了1步驟了,由於單態的資源共享,則私有變數user被修改為user2

這種情況下,user1的步驟3用到的user.getId()實際用到是user2的物件。

 

而如果是prototype的話,就不會出現資源共享的問題。

對於SSH來說,Bean的配置是沒錯的,配置為singleton ;實際應該是這個例子不應該用私有變數。這樣就使得這個Bean

由無狀態變成了有狀態Bean.還是應該儘量使用無狀態Bean.如果在程式中出現私有變數,儘量替換為引數。
對於每個訪問私有變數的方法增加變數傳入或者通過ThreadLocal來獲取也是不錯的方法。



相關文章