Spring框架是依賴注入的事實上的框架,在開發(fā)可擴展、彈性和安全的云原生環(huán)境中具有良好的記錄。
在使用Spring Beans時,初學者經常會對Spring beans和它們的作用域感到有些困惑。
以下是我對Singleton和Prototype Bean作用域的簡單示例進行闡述的嘗試。
Singleton Bean作用域:正如其名稱所示,作用域為Singleton的beans在Spring應用程序上下文中只有一個實例可用,然而值得注意的是,同一bean在Spring常量中可以具有不同的Bean名稱下?lián)碛卸鄠€實例。
這個想法與_Singleton設計模式_的概念有些不同,后者表示一旦將JAVA類設計為單例,JVM將在內存中只有單個實例可用。
Illustration 1.0 下面的插圖顯示了一個賬戶服務Spring bean,該bean可以具有不同的名稱,同一服務在Spring上下文中可以存在兩個不同的名稱。
當我們在Java應用程序中引用一個singleton類時,該類只有一個實例可用,然而在Spring中,Singleton并不意味著上下文中只有一個該類型的實例,它可以有多個具有不同名稱的該類型實例。
Prototype Bean作用域:當應用程序程序員將bean的作用域定義為Prototype時,這意味著每次有人請求引用一個bean時,Spring框架會返回全新的bean實例。Spring框架管理對象類型。
Illustration 1.1: 下面的插圖定義了一個Prototype作用域的bean,并解釋了每次我們請求Spring時,Spring都會提供所請求的bean的新實例。
為什么要讓一個bean具有Prototype作用域?
Prototype作用域是為了避免兩個線程在訪問Singleton Bean時出現(xiàn)競爭條件。由于多線程環(huán)境的交錯性質,這是一個經典的并發(fā)問題,操作的結果是不可預測的。因此,為了確保每個線程都獲得自己的bean副本,開發(fā)人員希望確保每個線程都獲得自己的副本。
什么是競爭條件?
以股票應用程序為例。股票價格每秒鐘更新一次,并且用于為特定股票ID更新股票價格的代碼是在并發(fā)上下文中編寫的,這意味著可能有多個調用者試圖更新股票X的價格。考慮一個一系列步驟的情況:
1.Mike試圖將股票X的價格更新為110美元。2.Mike讀取股票X的價格并將其增加到120美元。3.與此同時,在Mike將此寫入主內存之前,他去了洗手間。4.Bob拿著咖啡回來,看到屏幕上的舊股票價值為105,他將股票X的價值更新為125美元。5.Mike回來,然后將股票X的值再次更新為120美元。6.由于這個構造,Mike想要對股票X進行的更新對Bob是不可見的,他再次覆蓋了它。7.這是典型的競爭條件,我希望每個人都理解,就像Mike和Bob可以在這里被線程A和線程B替換一樣,在并發(fā)環(huán)境中。
如果StockPrice被定義為Prototype作用域的bean,則每個線程都會獲得其自己的StockPrice副本,它們不會互相干擾。但是,獲得Stock價格的不同副本并不消除對給定股票的Stock價格更新進行同步的需要,它需要在一系列原子步驟中完成,但為了避免復雜性,我們可以略過這個討論,以便理解Prototype Bean作用域。
Illustration 1.2: 下面的插圖定義了一個Prototype作用域的bean,并解釋了每個線程都會獲得Prototype bean的新實例。
總結:
1.默認情況下,Spring bean的作用域是Singleton。2.Singleton作用域的bean在Spring應用程序上下文中可以具有不同的名稱下的多個實例。3.Prototype bean是Spring框架提供的一個約定,每次請求時都會由框架提供bean的新實例。4.Prototype作用域的bean可以用于Singleton作用域的bean,但應該注意我們如何從上下文中獲取該bean,因為如果將Prototype bean定義在Singleton bean內部,則Spring提供的原型bean實例只會有一個,這違背了其自身的目的。5.為了避免競爭條件,可以使用Prototype Bean作用域。