一篱蝇、Bean 的完整生命周期
1.1 Bean的核心構(gòu)造過程
在傳統(tǒng)的Java應(yīng)用中催式,bean的生命周期很簡(jiǎn)單,使用Java關(guān)鍵字 new 進(jìn)行Bean 的實(shí)例化呜舒,然后該Bean 就能夠使用了锭汛。一旦bean不再被使用,則由Java自動(dòng)進(jìn)行垃圾回收袭蝗。相比之下唤殴,Spring管理Bean的生命周期就復(fù)雜多了,正確理解Bean 的生命周期非常重要到腥,因?yàn)镾pring對(duì)Bean的管理可擴(kuò)展性非常強(qiáng)朵逝,下面展示了一個(gè)Bean的構(gòu)造過程:
如上圖所示,Bean 的生命周期還是比較復(fù)雜的乡范,下面來對(duì)上圖每一個(gè)步驟做文字描述:
Spring啟動(dòng)配名,查找并加載需要被Spring管理的bean,進(jìn)行Bean的實(shí)例化
Bean實(shí)例化后對(duì)將Bean的引入和值注入到Bean的屬性中
如果Bean實(shí)現(xiàn)了BeanNameAware接口的話晋辆,Spring將Bean的Id傳遞給setBeanName()方法
如果Bean實(shí)現(xiàn)了BeanFactoryAware接口的話渠脉,Spring將調(diào)用setBeanFactory()方法,將BeanFactory容器實(shí)例傳入
如果Bean實(shí)現(xiàn)了ApplicationContextAware接口的話瓶佳,Spring將調(diào)用Bean的setApplicationContext()方法连舍,將bean所在應(yīng)用上下文引用傳入進(jìn)來。
如果Bean實(shí)現(xiàn)了BeanPostProcessor接口,Spring就將調(diào)用他們的postProcessBeforeInitialization()方法索赏。
如果Bean 實(shí)現(xiàn)了InitializingBean接口盼玄,Spring將調(diào)用他們的afterPropertiesSet()方法。類似的潜腻,如果bean使用init-method聲明了初始化方法埃儿,該方法也會(huì)被調(diào)用
如果Bean 實(shí)現(xiàn)了BeanPostProcessor接口,Spring就將調(diào)用他們的postProcessAfterInitialization()方法融涣。
此時(shí)童番,Bean已經(jīng)準(zhǔn)備就緒,可以被應(yīng)用程序使用了威鹿。他們將一直駐留在應(yīng)用上下文中剃斧,直到應(yīng)用上下文被銷毀。
如果bean實(shí)現(xiàn)了DisposableBean接口忽你,Spring將調(diào)用它的destroy()接口方法幼东,同樣,如果bean使用了destory-method 聲明銷毀方法科雳,該方法也會(huì)被調(diào)用根蟹。
1.2 Bean的全部構(gòu)造過程(超詳細(xì))
1.1節(jié)介紹了Spring 中Bean的核心接口和生命周期,還有另外的初始化過程涉及的接口糟秘,摘自org.springframework.beans.factory.BeanFactory简逮, 全部相關(guān)接口如下:
Bean的初始化:
BeanNameAware.setBeanName() 在創(chuàng)建此bean的bean工廠中設(shè)置bean的名稱,在普通屬性設(shè)置之后調(diào)用尿赚,在InitializinngBean.afterPropertiesSet()方法之前調(diào)用.
** BeanClassLoaderAware.setBeanClassLoader(): 在普通屬性設(shè)置之后散庶,InitializingBean.afterPropertiesSet()之前調(diào)用**
** BeanFactoryAware.setBeanFactory() : 回調(diào)提供了自己的bean實(shí)例工廠,在普通屬性設(shè)置之后凌净,在InitializingBean.afterPropertiesSet()或者自定義初始化方法之前調(diào)用**
** EnvironmentAware.setEnvironment(): 設(shè)置environment在組件使用時(shí)調(diào)用**
** EmbeddedValueResolverAware.setEmbeddedValueResolver(): 設(shè)置StringValueResolver 用來解決嵌入式的值域問題**
** ResourceLoaderAware.setResourceLoader(): 在普通bean對(duì)象之后調(diào)用悲龟,在afterPropertiesSet 或者自定義的init-method 之前調(diào)用,在 ApplicationContextAware 之前調(diào)用泻蚊。**
** ApplicationEventPublisherAware.setApplicationEventPublisher(): 在普通bean屬性之后調(diào)用,在初始化調(diào)用afterPropertiesSet 或者自定義初始化方法之前調(diào)用丑婿。在 ApplicationContextAware 之前調(diào)用性雄。**
** MessageSourceAware.setMessageSource(): 在普通bean屬性之后調(diào)用,在初始化調(diào)用afterPropertiesSet 或者自定義初始化方法之前調(diào)用羹奉,在 ApplicationContextAware 之前調(diào)用秒旋。**
** ApplicationContextAware.setApplicationContext(): 在普通Bean對(duì)象生成之后調(diào)用,在InitializingBean.afterPropertiesSet之前調(diào)用或者用戶自定義初始化方法之前诀拭。在ResourceLoaderAware.setResourceLoader迁筛,ApplicationEventPublisherAware.setApplicationEventPublisher,MessageSourceAware之后調(diào)用耕挨。**
** ServletContextAware.setServletContext(): 運(yùn)行時(shí)設(shè)置ServletContext细卧,在普通bean初始化后調(diào)用尉桩,在InitializingBean.afterPropertiesSet之前調(diào)用,在 ApplicationContextAware 之后調(diào)用注:是在WebApplicationContext 運(yùn)行時(shí)**
** BeanPostProcessor.postProcessBeforeInitialization() : 將此BeanPostProcessor 應(yīng)用于給定的新bean實(shí)例 在任何bean初始化回調(diào)方法(像是InitializingBean.afterPropertiesSet或者自定義的初始化方法)之前調(diào)用贪庙。這個(gè)bean將要準(zhǔn)備填充屬性的值蜘犁。返回的bean示例可能被普通對(duì)象包裝,默認(rèn)實(shí)現(xiàn)返回是一個(gè)bean止邮。**
** BeanPostProcessor.postProcessAfterInitialization() : 將此BeanPostProcessor 應(yīng)用于給定的新bean實(shí)例 在任何bean初始化回調(diào)方法(像是InitializingBean.afterPropertiesSet或者自定義的初始化方法)之后調(diào)用这橙。這個(gè)bean將要準(zhǔn)備填充屬性的值。返回的bean示例可能被普通對(duì)象包裝**
** InitializingBean.afterPropertiesSet(): 被BeanFactory在設(shè)置所有bean屬性之后調(diào)用(并且滿足BeanFactory 和 ApplicationContextAware)导披。**
Bean的銷毀:
在BeanFactory 關(guān)閉的時(shí)候屈扎,Bean的生命周期會(huì)調(diào)用如下方法:
** DestructionAwareBeanPostProcessor.postProcessBeforeDestruction(): 在銷毀之前將此BeanPostProcessor 應(yīng)用于給定的bean實(shí)例。能夠調(diào)用自定義回調(diào)撩匕,像是DisposableBean 的銷毀和自定義銷毀方法鹰晨,這個(gè)回調(diào)僅僅適用于工廠中的單例bean(包括內(nèi)部bean)。**
實(shí)現(xiàn)了自定義的destory()方法
二滑沧、Bean 的生命周期驗(yàn)證
2.1 驗(yàn)證Bean生命周期的過程
public class Book implements BeanNameAware,BeanFactoryAware,
** ApplicationContextAware,InitializingBean,DisposableBean {**
** private String bookName;**
** public Book(){**
** System.out.println("Book Initializing ");**
** }**
** public void setBeanFactory(BeanFactory beanFactory) throws BeansException {**
** System.out.println("Book.setBeanFactory invoke");**
** }**
** public void setBeanName(String name) {**
** System.out.println("Book.setBeanName invoke");**
** }**
** public void destroy() throws Exception {**
** System.out.println("Book.destory invoke");**
** }**
** public void afterPropertiesSet() throws Exception {**
** System.out.println("Book.afterPropertiesSet invoke");**
** }**
** public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {**
** System.out.println("Book.setApplicationContext invoke");**
** }**
** public String getBookName() {**
** return bookName;**
** }**
** public void setBookName(String bookName) {**
** this.bookName = bookName;**
** System.out.println("setBookName: Book name has set.");**
** }**
** public void myPostConstruct(){**
** System.out.println("Book.myPostConstruct invoke");**
** }**
** // 自定義初始化方法**
** @PostConstruct**
** public void springPostConstruct(){**
** System.out.println("@PostConstruct");**
** }**
** public void myPreDestory(){**
** System.out.println("Book.myPreDestory invoke");**
** System.out.println("---------------destroy-----------------");**
** }**
** // 自定義銷毀方法**
** @PreDestroy**
** public void springPreDestory(){**
** System.out.println("@PreDestory");**
** }**
** @Override**
** protected void finalize() throws Throwable {**
** System.out.println("------inside finalize-----");**
** }**
}
public class MyBeanPostProcessor implements BeanPostProcessor {
// 容器加載的時(shí)候會(huì)加載一些其他的bean并村,會(huì)調(diào)用初始化前和初始化后方法 // 這次只關(guān)注book(bean)的生命周期 public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if(bean instanceof Book){ System.out.println("MyBeanPostProcessor.postProcessBeforeInitialization"); } return bean; } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if(bean instanceof Book){ System.out.println("MyBeanPostProcessor.postProcessAfterInitialization"); } return bean; }
}
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 掃描bean -->
<context:component-scan base-package="com.bean.lifecycle"/>
<!-- 實(shí)現(xiàn)了用戶自定義初始化和銷毀方法 -->
<bean id="book" class="com.bean.lifecycle.Book" init-method="myPostConstruct" destroy-method="myPreDestory">
<!-- 注入bean 屬性名稱 -->
<property name="bookName" value="thingking in java" />
</bean>
<!--引入自定義的BeanPostProcessor-->
<bean class="com.bean.lifecycle.MyBeanPostProcessor"/>
</beans>
測(cè)試結(jié)果如下:
Book Initializing
setBookName: Book name has set.
Book.setBeanName invoke
Book.setBeanFactory invoke
Book.setApplicationContext invoke
MyBeanPostProcessor.postProcessBeforeInitialization
@PostConstruct
Book.afterPropertiesSet invoke
Book.myPostConstruct invoke
MyBeanPostProcessor.postProcessAfterInitialization
Book name = thingking in java
@PreDestory
Book.destory invoke
Book.myPreDestory invoke
---------------destroy————————
完整的測(cè)試結(jié)果:
Book Initializing
setBookName: Book name has set.
Book.setBeanName invoke
Book.setBeanFactory invoke
Book.setApplicationContext invoke
MyBeanPostProcessor.postProcessBeforeInitialization
@PostConstruct
Book.afterPropertiesSet invoke
Book.myPostConstruct invoke
MyBeanPostProcessor.postProcessAfterInitialization
Book name = thingking in java
@PreDestory
Book.destory invoke
Book.myPreDestory invoke
---------------destroy-----------------
Book Initializing
設(shè)置BookSystem 的屬性值
Book.setBeanName invoke
SubBookClass.setBeanClassLoader() 方法被調(diào)用了
Book.setBeanFactory invoke
SubBookClass.setEnvironment() 方法被調(diào)用了
SubBookClass.setEmbeddedValueResolver() 方法被調(diào)用了
SubBookClass.setResourceLoader() 方法被調(diào)用了
SubBookClass.setApplicationEventPublisher() 方法被調(diào)用了
SubBookClass.setMessageSource() 方法被調(diào)用了
Book.setApplicationContext invoke
MyBeanPostProcessor.postProcessBeforeInitialization
Book.afterPropertiesSet invoke
Book.myPostConstruct invoke
MyBeanPostProcessor.postProcessAfterInitialization
BookSystemName = Java System
Book.destory invoke
Book.myPreDestory invoke