Spring的Dao Service採用單例模式+ThreadLoca模式實現線程安全

 在使用Spring時,很多人可能對Spring中爲什麼DAO和Service對象採用單實例方式很迷惑,這些讀者是這麼認爲的:
    DAO對象必須包含一個數據庫的連接Connection,而這個Connection不是線程安全的,所以每個DAO都要包含一個不同的Connection對象實例,這樣一來DAO對象就不能是單實例的了。
    上述觀點對了一半。對的是“每個DAO都要包含一個不同的Connection對象實例”這句話,錯的是“DAO對象就不能是單實例”。
    其實Spring在實現Service和DAO對象時,使用了ThreadLocal這個類,這個是一切的核心! 如果你不知道什麼事ThreadLocal

Spring使用ThreadLocal解決線程安全問題:

    Spring中DAO和Service都是以單實例的bean形式存在,Spring通過ThreadLocal類將有狀態的變量(例如數據庫連接Connection)本地線程化,從而做到多線程狀況下的安全。在一次請求響應的處理線程中, 該線程貫通展示、服務、數據持久化三層,通過ThreadLocal使得所有關聯的對象引用到的都是同一個變量。 
    參考下面代碼,這個是《Spring3.x企業應用開發實戰中的例子》
[java] view plain copy
 print?
  1. public class SqlConnection {    
  2.     //①使用ThreadLocal保存Connection變量    
  3.     privatestatic ThreadLocal <Connection>connThreadLocal = newThreadLocal<Connection>();    
  4.     publicstatic Connection getConnection() {    
  5.        // ②如果connThreadLocal沒有本線程對應的Connection創建一個新的Connection,    
  6.        // 並將其保存到線程本地變量中。    
  7.        if (connThreadLocal.get() == null) {    
  8.            Connection conn = getConnection();    
  9.            connThreadLocal.set(conn);    
  10.            return conn;    
  11.        } else {    
  12.            return connThreadLocal.get();    
  13.            // ③直接返回線程本地變量    
  14.        }    
  15.     }    
  16.     public voidaddTopic() {    
  17.        // ④從ThreadLocal中獲取線程對應的Connection    
  18.        try {    
  19.            Statement stat = getConnection().createStatement();    
  20.        } catch (SQLException e) {    
  21.            e.printStackTrace();    
  22.        }    
  23.     }    
  24. }  
這個是例子展示了不同線程使用TopicDao時如何使得每個線程都獲得不同的Connection實例副本,同時保持TopicDao本身是單實例。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章