如果問spring中都有什麼作用域的bean、相信很多人都會回答「單例」,對的,如果這樣你只回答了一種。
spring中默認所有的bean都是作為單例(singleton)的形式創建的。不管bean被注入到其他的bean多少次,每次注入的都是同一個實例。
大多數情況下,單例bean還是一個很理想的方案。但有時它也不是理想的方案。舉一個最簡單的例子吧,比如大家所熟悉的淘寶、京東中的購物車,如果bean是單例的,那成千上萬個用戶使用的都是同一個購物車的bean,想想可能嗎?不可能,spring早已經為我們想好了方案。現在我說下sping定義的多種作用域。
單例(singleton):在整個應用中,只創建bean的一個實例。原型(prototype):每次注入或者通過spring應用上下文獲取的時候,都會創建一個新的bean實例。會話(session):在web應用中,為每個會話創建一個bean實例。請求(request):在web應用中,為每個請求創建一個bean實例。一、bean的創建(單例、原型)
我先說下單例和原型在bean中的指定
xml肯定是大家不陌生的:需要指定scope就ok了
另外一種是組件掃描或者聲明bean的方式,我們使用ConfigurableBeanFactory來指定
不知道大家有沒有發現、我為什麼只說了單例和原型
你會發現它ConfigurableBeanFactory就有這2種定義。
二、會話和請求
正如我上面的例子(購物車)所說、web應有中如果能夠實例化在會話和請求中共享的bean,是一件非常不錯的事情。
這裡要認真看下、因為涉及到了代理,也有可能你一個不注意,項目都啟動不起來了,我就拿「會話」講解了,「請求」同理。
使用WebApplicationContext,proxyMode來指定
大家應該對proxyMode = ScopedProxyMode.INTERFACES不理解吧,它主要目的就是為了解決會話和請求作用域bean注入到單例bean中所遇見的問題。
我在再創建一個單例bean講解。
我這StoreService注入了ShoppingCart,但是問題出來了,由於StoreService是單例,一啟動就會創建,我這個ShoppingCart是基於會話的,也就是說只有某個用戶進入系統,創建會話,這個bean才被創建,如果這樣,項目啟動去注入這個bean就會出問題,所以才使用proxyMode 目的使spring不會將實際的ShoppingCart注入到StoreService,而是注入ShoppingCart的代理,只有StoreService真正的調用了ShoppingCart中的方法,才會調用真正的ShoppingCart。
大家都應該知道代理有2種吧,一種是基於接口的、一種是基於類的(CGLib)。
上面的示例是基於接口的,那麼基於類要怎麼創建呢,其實很簡單,
將代理改成proxyMode = ScopedProxyMode.TARGET_CLASS即可。
三、xml聲明作用域代理
會話和請求我說的都是javaConfig的配置方式,現在還是會有很多人使用xml來配置(因為小編就在使用xml配置),我順便也說下xml如何配置。
xml想要設置代理模式,我們需要使用spring aop命名空間的一個新元素。
<aop:scoped-proxy/>
<aop:scoped-proxy/>默認情況下會使用CGLib代理,將proxy-target-class設置為false,就是基於接口代理。
到此spring的4中作用域說完了,如果大家有什麼疑問會不解、在下面評論、隨時解答,希望能給你們帶來幫助。