Spring作為當(dāng)前Java最流行、最強(qiáng)大的輕量級(jí)框架奋蔚,受到了程序員的熱烈歡迎窥浪。準(zhǔn)確的了解Spring Bean的生命周期是非常必要的。我們通常使用ApplicationContext作為Spring容器愿险。這里颇蜡,我們講的也是 ApplicationContext中Bean的生命周期。而實(shí)際上BeanFactory也是差不多的辆亏,只不過處理器需要手動(dòng)注冊(cè)风秤。
1、生命周期流程圖
Spring Bean的完整生命周期從創(chuàng)建Spring容器開始扮叨,直到最終Spring容器銷毀Bean缤弦,這其中包含了一系列關(guān)鍵點(diǎn)。
若容器注冊(cè)了以上各種接口彻磁,程序那么將會(huì)按照以上的流程進(jìn)行碍沐。下面將仔細(xì)講解各接口作用。
2衷蜓、實(shí)現(xiàn)過程詳解
2.1. 初始化
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)实夹。
2.2. 銷毀
在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()方法
3匀们、示例演示
為了驗(yàn)證Bean生命周期的過程缴淋,實(shí)例代碼如下:
Book.class:
public class Book implements BeanNameAware, BeanFactoryAware,
ApplicationContextAware, InitializingBean, DisposableBean,BeanClassLoaderAware,
EnvironmentAware,EmbeddedValueResolverAware,ResourceLoaderAware,
ApplicationEventPublisherAware,MessageSourceAware {
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 void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("BookClass.setBeanClassLoader() 方法被調(diào)用了");
}
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
System.out.println("BookClass.setApplicationEventPublisher() 方法被調(diào)用了");
}
public void setEmbeddedValueResolver(StringValueResolver resolver) {
System.out.println("BookClass.setEmbeddedValueResolver() 方法被調(diào)用了");
}
public void setEnvironment(Environment environment) {
System.out.println("BookClass.setEnvironment() 方法被調(diào)用了");
}
public void setMessageSource(MessageSource messageSource) {
System.out.println("BookClass.setMessageSource() 方法被調(diào)用了");
}
public void setResourceLoader(ResourceLoader resourceLoader) {
System.out.println("BookClass.setResourceLoader() 方法被調(diào)用了");
}
}
自定義實(shí)現(xiàn)BeanPostProcessor 的MyBeanPostProcessor
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;
}
}
在resources 目錄下新建Bean-Lifecycle.xml
<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>
做一個(gè)啟動(dòng)類的測(cè)試泄朴,新建SpringBeanLifecycleApplication
public class SpringBeanLifecycleApplication {
public static void main(String[] args) throws InterruptedException {
// 簡(jiǎn)單版的Bean生命周期加載過程
ApplicationContext context = new ClassPathXmlApplicationContext("Bean-Lifecycle.xml");
Book book = (Book)context.getBean("book");
System.out.println("Book name = " + book.getBookName());
((ClassPathXmlApplicationContext) context).destroy();
}
}
啟動(dòng)測(cè)試重抖,輸出結(jié)果如下
Book Initializing
setBookName: Book name has set.
Book.setBeanName invoke
BookClass.setBeanClassLoader() 方法被調(diào)用了
Book.setBeanFactory invoke
BookClass.setEnvironment() 方法被調(diào)用了
BookClass.setEmbeddedValueResolver() 方法被調(diào)用了
BookClass.setResourceLoader() 方法被調(diào)用了
BookClass.setApplicationEventPublisher() 方法被調(diào)用了
BookClass.setMessageSource() 方法被調(diào)用了
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-----------------