關于spring bean的生命周期,是深入學習spring的基礎,也是難點,本篇文章将采用代碼+圖文結論的方式來闡述spring bean的生命周期,
本篇文章将闡述清楚下圖。

一 項目結構及源碼
1.程式目錄結構
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="com.demo.dao.UserDao" id="userDao" scope="singleton" init-method="myInit" destroy-method="myDestroy">
<property name="userName" value="Alan_beijing"/>
</bean>
<bean class="com.demo.dao.MyBeanPostProcessor" id="myBeanPostProcessor"/>
</beans>
3.UserDao.java
package com.demo.dao;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.apache.log4j.Logger;
public class UserDao implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean,
DisposableBean{
private String userName;
private int count = 0;
public String getUserName() {
return userName;
}
//2.屬性注入,注入屬性為userName
public void setUserName(String userName) {
count++;
System.out.println(count + ":注入屬性userName="+userName);
this.userName = userName;
}
//1.無參構造函數,執行個體化時調用該構造函數
public UserDao() {
count++;
System.out.println(count + ":調用構造函數UserDao()");
}
//3.實作BeanNameAware,擷取bean id
public void setBeanName(String s) {
count++;
System.out.println(count + ":調用setBeanName()擷取bean id,bean id=" + s);
}
//4.實作BeanFactoryAware,擷取bean工廠
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
count++;
System.out.println(count + ":調用setBeanFactory()擷取bean工廠,beanFactory=" + beanFactory);
}
//5.實作ApplicationContextAware,擷取bean上下文
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
count++;
System.out.println(count + ":調用setApplicationContext()擷取bean上下文,applicationContext=" + applicationContext);
}
//6.實作InitializingBean,擷取afterPropertiesSet
public void afterPropertiesSet() throws Exception {
count++;
System.out.println(count + ":調用afterPropertiesSet()");
}
//7.自定義初始化方法myInit()
public void myInit() {
count++;
System.out.println(count + ":調用自定義myInit()");
}
//8.實作DisposableBean,擷取destroy()
public void destroy() throws Exception {
count++;
System.out.println(count + ":destroy()");
}
//9.自定義銷毀方法myDestroy()
public void myDestroy() {
count++;
System.out.println(count + ":調用自定義destroy()");
}
}
4.MyBeanPostProcessor.java
package com.demo.dao;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class MyBeanPostProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("=====調用postProcessBeforeInitialization()=====");
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("=====調用postProcessAfterInitialization()=====");
return bean;
}
}
二 測試代碼及測試結果
1.test.java
package com.demo.test;
import com.demo.dao.UserDao;
import org.junit.Test;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
@Test
public void test() {
//定義容器并初始化
//ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
applicationContext.getBean(UserDao.class);
//隻有關閉容器時,才會調用destroy方法
applicationContext.registerShutdownHook();
}
}
2.測試結果
三 分析
通過如上測試結果,bean生命周期流程大緻如下:
1.裝配bean
bean裝配為bean生命周期第一環節。所謂裝配bean,指将java對象轉換為bean的過程。在該示例中,UserDao.jave和MyBeanPostProcessor通過xml方式轉化為bean。
注意:spring架構支援四種方式裝配bean:xml方式,java代碼方式,自動裝配和混合裝配方式
2.加載applicationContext.xml并執行個體化
加載并執行個體化bean為bean生命周期的第二環節。本文示例通過ClassPathXmlApplicationContext()來加載并,當bean為singleton時,該過程就執行個體化對象,而不需要等待
調用applicationContext.getBean()擷取bean時才執行個體化對象,這與prototype是不一樣的。
3.屬性注入
bean屬性注入為bean生命周期第三環節,采用反射方式注入bean.
4.實作BeanNameAware,擷取bean id
該過程為bean生命周期的第四環節,實作該接口,可以擷取bean的id
5.實作BeanFactoryAware,擷取bean 工廠
該過程為bean生命周期第五環節,通過實作BeanFactoryAware擷取bean工廠
6.實作ApplicationContextAware,擷取運用上下文
該過程為bean生命周期第六環節,通過實作ApplicationContextAware接口,擷取bean上下文
7.調用Bean後置處理器,before
該過程為bean生命周期第七環節,通過實作後置處理器BeanPostProcessor擷取before和after,該過程是通過AOP方式實作的,在before和after之間,發生如下8,9過程。
8.實作InitializingBean的afterPropertiesSet(),擷取初始化方法
該過程為bean生命周期第八環節,通過實作InitializingBean,擷取afterPropertiesSet()
9.調用自定義初始化方法,init-method
該過程為bean生命周期第九環節,實作自定義初始化方法
10.調用Bean後置處理器after
該過程為bean生命周期第十環節,後置處理器最後環節
11.關閉容器AbstractApplicationContext.registerShutDownHook()
該環節為bean生命周期第十一環節,關閉容器
12.調用DisposableBean的destroy()
該過程為bean生命周期第十二環節,實作DisposableBean接口,調用destroy()
13.調用定制化銷毀方法destroy-method
該過程為bean生命周期最後環節,調用自定義銷毀方法destroy-method
三 版權區
- 轉載部落格,必須注明部落格出處
- 部落客網址:http://www.cnblogs.com/wangjiming/
- 如您有新想法,歡迎提出,郵箱:[email protected]
- 專業.NET之家技術QQ群:490539956
- 專業化Java之家QQ群:924412846
- 有問必答QQ群:2098469527
- 一對一技術輔導QQ:2098469527