【Spring進階指南】Spring 爲啥默認把bean設計成單例的?

上次分享了Redis相關問題的分享, 【Redis面試題】Redis的字符串是怎麼實現的?以後今天想在分享一篇有關spring bean相關的內容。原問題大概是先問了我spring bean做用域相關問題,最後問了我spring 爲啥默認把bean設計成單例的?
我打算從如下幾方面講起:html

  • 單例bean與原型bean的區別
  • 單例bean的優點
  • 單例bean的劣勢
  • 總結

熟悉spring開發的朋友都知道spring 提供了5種scope分別是singleton, prototype, request, session,global session。以下圖是官方文檔上的截圖,感興趣的朋友能夠進去看看這五種分別有什麼不一樣。今天要介紹的是這五種中的前兩種,也是spring最初提供的bean scope singleton 和 prototype。java

spring 官方文檔介紹以下圖: 面試

更多內容能夠看官方文檔介紹,很是詳細: Spring bean做用域

單例bean與原型bean的區別

若是一個bean被聲明爲單例的時候,在處理屢次請求的時候在spring 容器裏只實例化出一個bean,後續的請求都公用這個對象,這個對象會保存在一個map裏面。當有請求來的時候會先從緩存(map)裏查看有沒有,有的話直接使用這個對象,沒有的話才實例化一個新的對象,因此這是個單例的。可是對於原型(prototype)bean來講當每次請求來的時候直接實例化新的bean,沒有緩存以及從緩存查的過程。算法

1.畫圖分析spring

2.源碼分析緩存

生成bean時先判斷單例的仍是原型的安全

若是是單例的則先嚐試從緩存裏獲取,沒有在新建立session

結論:

1.單例的bean只有第一次建立新的bean 後面都會複用該bean,因此不會頻繁建立對象。併發

2.原型的bean每次都會新建立jvm

單例bean的優點

因爲不會每次都新建立新對象因此有一下幾個性能上的優點: 1.減小了新生成實例的消耗 新生成實例消耗包括兩方面,第一,spring會經過反射或者cglib來生成bean實例這都是耗性能的操做,其次給對象分配內存也會涉及複雜算法

2.減小jvm垃圾回收 因爲不會給每一個請求都新生成bean實例,因此天然回收的對象少了

3.能夠快速獲取到bean 由於單例的獲取bean操做除了第一次生成以外其他的都是從緩存裏獲取的因此很快

有關bean實例化相關能夠看着篇文章:Spring 源碼分析之 bean 實例化原理

單例bean的劣勢

單例的bean一個很大的劣勢就是他不能作到線程安全!!!,因爲全部請求都共享一個bean實例,因此這個bean要是有狀態的一個bean的話可能在併發場景下出現問題,而原型的bean則不會有這樣問題(但也有例外,好比他被單例bean依賴),由於給每一個請求都新建立實例。關於這方面我正在準備寫一篇文章,在整理當中,感興趣的朋友能夠關注我,我後續寫一篇詳細的文章。

總結

Spring 爲啥把bean默認設計成單例?
答案:爲了提升性能!!!從幾個方面,1.少建立實例2.垃圾回收3.緩存快速獲取
單例有啥劣勢?
若是是有狀態的話在併發環境下線程不安全

有關spring bean的線程安全相關話題,我會在下一篇文章中寫出。



歡迎加羣一塊兒討論MySQL,Spring , java等。


其餘文章

【Redis面試題】Redis的字符串是怎麼實現的?

Spring 源碼分析之 bean 實例化原理?

Spring 源碼分析之 bean 依賴注入原理(注入屬性)

Spring源碼分析之 lazy-init 實現原理

相關文章
相關標籤/搜索