spring bean的作用域和生命周期
一、spring bean的作用域
五種作用域:singleton、prototype、request、session、globalSession
request、session和global session三種作用域僅在基于web的應用中使用(不必關心你所采用的是什么web應用框架),只能用在基于web的Spring ApplicationContext環境。
1.singleton
當一個bean的作用域為Singleton,那么Spring IoC容器中只會存在一個共享的bean實例,并且所有對bean的請求,只要id與該bean定義相匹配,則只會返回bean的同一實例。Singleton是單例類型,就是在創建起容器時就同時自動創建了一個bean的對象,不管你是否使用,他都存在了,每次獲取到的對象都是同一個對象。注意,Singleton作用域是Spring中的缺省作用域。要在XML中將bean定義成singleton,可以這樣配置:
<bean id="ServiceImpl" class="cn.csdn.service.ServiceImpl" scope="singleton">2.prototype
當一個bean的作用域為Prototype,表示一個bean定義對應多個對象實例。Prototype作用域的bean會導致在每次對該bean請求(將其注入到另一個bean中,或者以程序的方式調用容器的getBean()方法)時都會創建一個新的bean實例。Prototype是原型類型,它在我們創建容器的時候并沒有實例化,而是當我們獲取bean的時候才會去創建一個對象,而且我們每次獲取到的對象都不是同一個對象。根據經驗,對有狀態的bean應該使用prototype作用域,而對無狀態的bean則應該使用singleton作用域。在XML中將bean定義成prototype,可以這樣配置
<bean id="account" class="com.foo.DefaultAccount" scope="prototype"/> 或者 <bean id="account" class="com.foo.DefaultAccount" singleton="false"/>3.request
當一個bean的作用域為Request,表示在一次HTTP請求中,一個bean定義對應一個實例;即每個HTTP請求都會有各自的bean實例,它們依據某個bean定義創建而成。該作用域僅在基于web的Spring ApplicationContext情形下有效??紤]下面bean定義:
<bean id="loginAction" class="cn".csdn.LoginAction" scope="request"/>針對每次HTTP請求,Spring容器會根據loginAction bean的定義創建一個全新的LoginAction bean實例,且該loginAction bean實例僅在當前HTTP request內有效,因此可以根據需要放心的更改所建實例的內部狀態,而其他請求中根據loginAction bean定義創建的實例,將不會看到這些特定于某個請求的狀態變化。當處理請求結束,request作用域的bean實例將被銷毀。
4.session
當一個bean的作用域為Session,表示在一個HTTP Session中,一個bean定義對應一個實例。該作用域僅在基于web的Spring ApplicationContext情形下有效??紤]下面bean定義:
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>針對某個HTTP Session,Spring容器會根據userPreferences bean定義創建一個全新的userPreferences bean實例,且該userPreferences bean僅在當前HTTP Session內有效。與request作用域一樣,可以根據需要放心的更改所創建實例的內部狀態,而別的HTTP Session中根據userPreferences創建的實例,將不會看到這些特定于某個HTTP Session的狀態變化。當HTTP Session最終被廢棄的時候,在該HTTP Session作用域內的bean也會被廢棄掉。
5.globalSession
當一個bean的作用域為Global Session,表示在一個全局的HTTP Session中,一個bean定義對應一個實例。典型情況下,僅在使用portlet context的時候有效。該作用域僅在基于web的Spring ApplicationContext情形下有效。考慮下面bean定義:
<bean id="user" class="com.foo.Preferences "scope="globalSession"/>global session作用域類似于標準的HTTP Session作用域,不過僅僅在基于portlet的web應用中才有意義。Portlet規范定義了全局Session的概念,它被所有構成某個portlet web應用的各種不同的portlet所共享。在global session作用域中定義的bean被限定于全局portlet Session的生命周期范圍內。
二、bean的生命周期
?
1.Bean的建立:由BeanFactory讀取Bean定義文件,并生成各個實例。
? 2.Setter注入:執行Bean的屬性依賴注入。
3.BeanNameAware的setBeanName():如果Bean類實現了org.springframework.beans.factory.BeanNameAware接口,則執行其setBeanName()方法。
4.BeanFactoryAware的setBeanFactory():如果Bean類實現了org.springframework.beans.factory.BeanFactoryAware接口,則執行其setBeanFactory()方法。
5.BeanPostProcessors的processBeforeInitialization():容器中如果有實現org.springframework.beans.factory.BeanPostProcessors接口的實例,則任何Bean在初始化之前都會執行這個實例的processBeforeInitialization()方法。
6.InitializingBean的afterPropertiesSet():如果Bean類實現了org.springframework.beans.factory.InitializingBean接口,則執行其afterPropertiesSet()方法。
7.Bean定義文件中定義init-method:在Bean定義文件中使用“init-method”屬性設定方法名稱,如下:
<bean id="demoBean" class="com.yangsq.bean.DemoBean" init-method="initMethod">.......</bean>這時會執行initMethod()方法,注意,這個方法是不帶參數的。
8.BeanPostProcessors的processAfterInitialization():容器中如果有實現org.springframework.beans.factory.BeanPostProcessors接口的實例,則任何Bean在初始化之前都會執行這個實例的processAfterInitialization()方法。
9.DisposableBean的destroy():在容器關閉時,如果Bean類實現了org.springframework.beans.factory.DisposableBean接口,則執行它的destroy()方法。
10.Bean定義文件中定義destroy-method:在容器關閉時,可以在Bean定義文件中使用“destory-method”定義的方法
<bean id="demoBean" class="com.yangsq.bean.DemoBean" destory-method="destroyMethod">....... </bean>?
其實很多時候我們并不會真的去實現上面說描述的那些接口,那么下面我們就除去那些接口,針對bean的單例和非單例來描述下bean的生命周期:
2.1 單例管理的對象
當scope=”singleton”,即默認情況下,會在啟動容器時(即實例化容器時)時實例化。但我們可以指定Bean節點的lazy-init=”true”來延遲初始化bean,這時候,只有在第一次獲取bean時才會初始化bean,即第一次請求該bean時才初始化。如下配置:
<bean id="ServiceImpl" class="cn.csdn.service.ServiceImpl" lazy-init="true"/>如果想對所有的默認單例bean都應用延遲初始化,可以在根節點beans設置default-lazy-init屬性為true,如下所示:
<beans default-lazy-init="true" …>默認情況下,Spring在讀取xml文件的時候,就會創建對象。在創建對象的時候先調用構造器,然后調用init-method屬性值中所指定的方法。對象在被銷毀的時候,會調用destroy-method屬性值中所指定的方法
2.2 非單例管理的對象
當scope=”prototype”時,容器也會延遲初始化bean,Spring讀取xml文件的時候,并不會立刻創建對象,而是在第一次請求該bean時才初始化(如調用getBean方法時)。在第一次請求每一個prototype的bean時,Spring容器都會調用其構造器創建這個對象,然后調用init-method屬性值中所指定的方法。對象銷毀的時候,Spring容器不會幫我們調用任何方法,因為是非單例,這個類型的對象有很多個,Spring容器一旦把這個對象交給你之后,就不再管理這個對象了。
對于作用域為prototype的bean,其destroy方法并沒有被調用。如果bean的scope設為prototype時,當容器關閉時,destroy方法不會被調用。對于prototype作用域的bean,有一點非常重要,那就是Spring不能對一個prototype bean的整個生命周期負責:容器在初始化、配置、裝飾或者是裝配完一個prototype實例后,將它交給客戶端,隨后就對該prototype實例不聞不問了。不管何種作用域,容器都會調用所有對象的初始化生命周期回調方法。但對prototype而言,任何配置好的析構生命周期回調方法都將不會被調用。清除prototype作用域的對象并釋放任何prototype bean所持有的昂貴資源,都是客戶端代碼的職責
?
轉載于:https://www.cnblogs.com/JavaZhangXu/p/10114950.html
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的spring bean的作用域和生命周期的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于CATALINA_BASE
- 下一篇: python (八)迭代器、生成器、列表