關於spring bean的生命週期,是深入學習spring的基礎,也是難點,本篇文章將採用代碼+圖文結論的方式來闡述spring bean的生命週期,本篇文章將闡述清楚下圖。
一 項目結構及源碼
1.程序目錄結構
2.applicationContext.xml
<?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