Spring原理解析(3)- Bean
Bean的生命週期
Bean的生命過程可以借鑑Servlet的生命過程,瞭解其生命過程對於不管是思想還是以後的使用都很有幫助;
Bean可以通過兩種方式進行載入,分別是使用BeanFactory 和 applicationContext, 下邊就這兩種方式進行Bean的宣告週期總結:
applicationContext:
1:Bean的建立:
容器尋找Bean的定義資訊並將其例項化,也就是new一個物件,。
2:屬性注入:
使用依賴注入,Spring按照Bean定義資訊配置Bean所有屬性,相當於呼叫set方法進行屬性set操作
3. 如果這個Bean實現了BeanNameAware介面,會呼叫它實現的setBeanName(String beanId)方法,此處傳遞的是Spring配置檔案中Bean的ID
4. 如果這個Bean實現了BeanFactoryAware介面,會呼叫它實現的setBeanFactory(),傳遞的是Spring工廠本身(可以用這個方法獲取到其他Bean)
5. 如果這個Bean實現了ApplicationContextAware介面,會呼叫setApplicationContext(ApplicationContext)方法,傳入Spring上下文,該方式同樣可以實現步驟4,但比4更好,以為ApplicationContext是BeanFactory的子介面,有更多的實現方法
6. 如果這個Bean關聯了BeanPostProcessor介面,將會呼叫postProcessBeforeInitialization(Object obj, String s)方法,BeanPostProcessor經常被用作是Bean內容的更改,並且由於這個是在Bean初始化結束時呼叫After方法,也可用於記憶體或快取技術
7.如果設定了initializingBean介面,則會呼叫實現的afterPropertiesSet()方法;
8. 如果這個Bean在Spring配置檔案中配置了init-method屬性會自動呼叫其配置的初始化方法【相當於定製方法】
9. 如果這個Bean關聯了BeanPostProcessor介面,將會呼叫postAfterInitialization(Object obj, String s)方法
10. 容器關閉,當Bean不再需要時,會經過清理階段,如果Bean實現了DisposableBean介面,會呼叫其實現的destroy方法,如果這個Bean的Spring配置中配置了destroy-method屬性,會自動呼叫其配置的銷燬方法
BeanFactory:
下邊對BeanFactory的生命週期過程進行分析,BeanFactory的生命週期相對於ApplicationContext來說相對簡化了一些;
下面用圖進行概括:
下面以BeanFactory為例,說明一個Bean的生命週期活動
- Bean的建立, 由BeanFactory讀取Bean定義檔案,並生成各個例項
- Setter注入,執行Bean的屬性依賴注入
- BeanNameAware的setBeanName(), 如果實現該介面,則執行其setBeanName方法
- BeanFactoryAware的setBeanFactory(),如果實現該介面,則執行其setBeanFactory方法
- InitializingBean的afterPropertiesSet(),如果實現了該介面,則執行其afterPropertiesSet()方法
- Bean定義檔案中定義init-method
- DisposableBean的destroy(),在容器關閉時,如果Bean類實現了該介面,則執行它的destroy()方法
- Bean定義檔案中定義destroy-method,在容器關閉時,可以在Bean定義檔案中使用“destory-method”定義的方法
對比:
如果使用ApplicationContext來維護一個Bean的生命週期,則基本上與上邊的流程相同,只不過在執行BeanNameAware的setBeanName()後,若有Bean類實現了org.springframework.context.ApplicationContextAware介面,則執行其setApplicationContext()方法,然後再進行BeanPostProcessors的processBeforeInitialization()
實際上,ApplicationContext除了向BeanFactory那樣維護容器外,還提供了更加豐富的框架功能,如Bean的訊息,事件處理機制等。
①ApplicationContext 介面繼承BeanFactory介面,Spring核心工廠是BeanFactory ,BeanFactory採取延遲載入,第一次getBean時才會初始化Bean, ApplicationContext是會在載入配置檔案時初始化Bean。
②ApplicationContext是對BeanFactory擴充套件,它可以進行國際化處理、事件傳遞和bean自動裝配以及各種不同應用層的Context實現
開發中基本都在使用ApplicationContext, web專案使用WebApplicationContext ,很少用到BeanFactory
Bean的作用域
singleton
當一個bean的作用域為singleton, 那麼Spring IoC容器中只會存在一個共享的bean例項,並且所有對bean的請求,只要id與該bean定義相匹配,則只會返回bean的同一例項。
prototype
Prototype作用域的bean會導致在每次對該bean請求(將其注入到另一個bean中,或者以程式的方式呼叫容器的getBean() 方法)時都會建立一個新的bean例項。根據經驗,對所有有狀態的bean應該使用prototype作用域,而對無狀態的bean則應該使用 singleton作用域
request
在一次HTTP請求中,一個bean定義對應一個例項;即每次HTTP請求將會有各自的bean例項, 它們依據某個bean定義建立而成。該作用 域僅在基於web的Spring ApplicationContext情形下有效。
session
在一個HTTP Session中,一個bean定義對應一個例項。該作用域僅在基於web的Spring ApplicationContext情形下有效。
global session
在一個全域性的HTTP Session中,一個bean定義對應一個例項。典型情況下,僅在使用portlet context的時候有效。該作用域僅在基於 web的Spring ApplicationContext情形下有效。
Bean注入屬性有哪幾種方式?
spring支援構造器注入和setter方法注入屬性
構造器注入,通過 <constructor-arg> 元素完成注入
setter方法注入, 通過<property> 元素完成注入【開發中常用方式】