Springboot中的Bean作用域

banq發表於2022-12-04

在 Spring 上下文中,bean 是將由 spring 的 ApplicationContext 建立和管理的類的例項。在spring-boot中,當我們對一個類進行@Component註解時,該類就有資格被spring的ApplicationContext管理。
當 spring 容器啟動時,它會掃描所有由@Component註釋註釋的類,然後建立該類的 bean。然後當你宣告欄位級或構造器級依賴注入時,bean 工廠將獲取例項並注入它。

什麼是Bean 作用域scope
Bean作用域是我們用@Scope註解定義的,它告訴應用程式上下文應該如何在整個應用程式生命週期中建立和展示特定的Bean。
作為一個例子,spring的預設Bean範圍是一個單子單例。
單子單例意味著當應用程式上下文啟動時,一個特定的Bean將被一次性建立,並在整個應用程式上下文中使用該Bean。

Spring中的Bean作用域

1、Singleton (預設作用域)

當你只用@Component註解一個類,而沒有@Scope註解時,這種型別的Bean將被建立。
在這個作用域中,當應用程式啟動時,一個特定的Bean將被一次性建立,並在整個應用程式中使用這個Bean。
這也適用於方法級Bean的建立。這意味著當我們在方法上使用@Bean註解時。

2、原型
在@Component註解之後,用@Scope(value=ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)進行註解,這種原型型別的Bean將被建立。
在這個範圍內,一個特定類的新例項將被建立並在每次請求該類的Bean時被注入。
這同樣適用於方法級Bean的建立。這意味著當我們在方法上使用@Bean註解時,我們需要定義@Scope(value=ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS) 

3、請求
在@Component註解之後,用@Scope(value=WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)進行註解,這種請求型別的bean將被建立。
這個範圍不適用於普通的獨立應用程式。這隻適用於java web應用程式的上下文。
在這個作用域內,一個特定類的新例項將被建立併為每個新的HTTP請求注入。

這將同樣適用於方法級Bean的建立。這意味著當我們在方法上使用@Bean註解時,我們需要定義@Scope(value=WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS) 

4、會話
當你用@Scope(value=WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)進行註解時,這種型別的bean將被建立。
這個作用域不適用於普通的獨立應用程式。這將適用於java web應用程式的上下文。
在這個作用域內,一個特定類的新例項將被建立併為HTTP請求的每個新會話注入。
這將同樣適用於方法級Bean的建立。這意味著當我們在方法上使用@Bean註解時,我們需要定義@Scope(value=WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS) 

5、Application
當你用@Scope(value=WebApplicationContext.SCOPE_APPLICATION, proxyMode = ScopedProxyMode.TARGET_CLASS)進行註解,這種型別的bean將被建立。
在這個作用域內,一個特定類的新例項將被建立,併為每個新的Web應用執行時間注入。
這與singleton更為相似,但在singleton中,每個ApplicationContext有一個例項,而這裡是每個ServletContext有一個例項。

6、自定義範圍
與其在spring-boot中使用預定義的作用域,我們可以建立自己的作用域並使用它。
在org.springframework.beans.factory.config包中有一個名為Scope的介面。我們需要從該介面實現我們自己的scope類。

為何需要?
瞭解這個 bean 作用域將在以下情況下幫助我們。
1、單例

  • 如果您要在 Web 應用程式上下文中儲存、更新和使用特定於 Web 應用程式的內容,那麼單例是最好的使用作用域。
  • 使用此範圍將節省記憶體,因為它將為 Web 應用程式上下文建立一個 bean。因此,除非您有某些特定要求,否則最好堅持使用此範圍。
  • 如果該類要提供一些功能性目的而不是為物件到物件儲存一些特定變數,則最好使用此範圍。更好地用於服務、儲存庫和實用程式類,因為這些型別的類主要具有函式而不是欄位。


2、原型
  • 如果您需要使用一些有狀態的元件,那麼這是一個很好的使用範圍。
  • 如果您需要使用具有非相互依賴輸入的執行緒或非同步流,那麼這是線上程內部使用的一個很好的 bean 作用域。


3、請求
  • 如果您需要一個有狀態元件來儲存一些特定於 HTTP 請求的詳細資訊,那麼這就是您應該選擇的作用域。
  • 如果您需要儲存一些請求標頭或 Auth 令牌並在稍後的流程中使用它們,那麼這就是您應該選擇的作用域。
  • 如果您需要在程式的每個步驟或每個類中儲存請求-響應的值,那麼這就是您應該用於特定物件的響應 bean 的作用域。


4、會話
  • 如果您需要一個有狀態元件來儲存一些特定於會話的詳細資訊,那麼這就是您應該選擇的作用域。
  • 如果您需要儲存一些當前會話使用者資訊並在整個會話活動中使用這些詳細資訊,那麼這是理想的使用作用域。


5、Application
  • 如果您需要跨多個 Web 應用程式上下文儲存和訪問詳細資訊,則不能使用單例,但可以使用此應用程式作用域 bean。
  • 一個 servlet 上下文可以有多個 Web上下文。

相關文章