Spring的Bean的生命周期
- Spring的Bean的生命周期
- 整體過程
- 實例化
- 初始化
- 服務
- 銷毀
- 循環依賴問題
- 完整生命周期演示
Spring的Bean的生命周期
Spring Bean的生命周期:從Bean的實例化之后,通過反射創建出對象之后,到Bean稱為一個完整的對象,接著被存儲到singletonObjects中,最后被銷毀的全過程。
整體過程
過程劃分:整體劃分為四個階段
Spring中Bean的創建實際上是在createBean方法中完成,但實際底層工作的是doCreateBean方法;方法所在的位置AbstractAutowireCapableBeanFactory中的doCreateBean,這里面存放的實際上存放的就是Bean生命周期的整個過程。
// AbstractAutowireCapableBeanFactory.java
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)throws BeanCreationException {// 1. beanWrapper是實例化bean的第一步BeanWrapper instanceWrapper = null;if (instanceWrapper == null) {instanceWrapper = createBeanInstance(beanName, mbd, args);}Object exposedObject = bean;try {// 2. populateBean方法進行屬性賦值populateBean(beanName, mbd, instanceWrapper);// 3. 調用initilizeBean進行spring初始化(省略了詳細的代碼步驟)exposedObject = initializeBean(beanName, exposedObject, mbd);}// 4. 銷毀try {registerDisposableBeanIfNecessary(beanName, bean, mbd);}return exposedObject;
}
實例化
實例化過程:Spring框架會取出BeanDefinition的信息進行判斷當前Bean的范圍是否是singleton的, 是否不是延遲加載的,是否不是FactoryBean等,最終將一個普通的singleton的Bean通過反射進行實例化;這個過程實際上是JVM在做,對象的創建過程可以參考之前寫的Java對象的創建過程里面有詳細的講解。
初始化
初始化:Bean創建之后還僅僅是個"半成品",還需要對Bean實例的屬性進行填充、執行一些Aware 接口方法、執行BeanPostProcessor方法、執行InitializingBean接口的初始化方法、執行自定義初始化init方法等。具體的流程如下:
-
屬性注入:
- 注入普通屬性,String、int或存儲基本類型的集合時,直接通過set方法的反射設置進去;
- 注入單向對象引用屬性時,從容器中getBean獲取后通過set方法反射設置進去,如果容器中沒有,則先創建被注入對象Bean實例(完成整個生命周期)后,在進行注入操作
- 注入雙向對象引用屬性時,就比較復雜了,涉及了循環引用(循環依賴)
-
BeanNameAware的setBeanName():
如果Bean類有實現org.springframework.beans.BeanNameAware接口,工廠調用Bean的setBeanName()方法傳遞Bean的ID。
-
BeanFactoryAware的setBeanFactory():
如果Bean類有實現org.springframework.beans.factory.BeanFactoryAware接口,工廠調用setBeanFactory()方法傳入工廠自身。
-
BeanPostProcessors的ProcessBeforeInitialization():
如果有org.springframework.beans.factory.config.BeanPostProcessors和Bean關聯,那么其postProcessBeforeInitialization()方法將被將被調用。
-
initializingBean的afterPropertiesSet():
如果Bean類已實現org.springframework.beans.factory.InitializingBean接口,則執行他的afterProPertiesSet()方法。
-
Bean定義文件中定義init-method:
如果配置文件中使用init-method屬性指定了初始化方法,那么Bean在實例化完成后將會調用該屬性指定的初始化方法進行Bean的初始化。
-
BeanPostProcessors的ProcessaAfterInitialization():
如果有任何的BeanPostProcessors實例與Bean實例關聯,則執行BeanPostProcessors實例的ProcessaAfterInitialization()方法。
服務
服務:使用階段。
銷毀
銷毀:當Bean不再需要時,會經過清理階段,如果Bean實現了DisposableBean這個接口,會調用那個其實現的destroy()方法;如果這個Bean的Spring配置中配置了destroy-method屬性,會自動調用其配置的銷毀方法。
循環依賴問題
注入雙向對象引用屬性時就會出現循環依賴
循環依賴:多個實體之間相互依賴并形成閉環的情況就叫做"循環依賴",也叫做"循環引用"
循環依賴問題spring已經給出了解決方法:三級緩存
Spring提供了三級緩存存儲 完整Bean實例 和 半成品Bean實例 ,用于解決循環引用問題
在DefaultListableBeanFactory的上四級父類DefaultSingletonBeanRegistry中提供如下三個Map
假如,UserService注入了一個UserDao,UserDao又注入了一個UserService,實例化過程如下:
- UserService 實例化對象,但尚未初始化,將UserService存儲到三級緩存
- UserService 屬性注入,需要UserDao,從緩存中獲取,沒有UserDao
- UserDao實例化對象,但尚未初始化,將UserDao存儲到到三級緩存
- UserDao屬性注入,需要UserService,從三級緩存獲取UserService,UserService從三級緩存移入二級緩存
- UserDao執行其他生命周期過程,最終成為一個完成Bean,存儲到一級緩存,刪除二三級緩存
- UserService 注入UserDao
- UserService執行其他生命周期過程,最終成為一個完成Bean,存儲到一級緩存,刪除二三級緩存
完整生命周期演示
-
導入坐標:spring context
-
創建實體類:Student,實現接口:
InitializingBean,BeanFactoryAware,BeanNameAware,ApplicationContextAware
public class Student implements InitializingBean,BeanFactoryAware,BeanNameAware,ApplicationContextAware{private String sname;public Student() {System.out.println("bean的無參構造方法");}public void setSname(String sname) {System.out.println("set方法賦值");this.sname = sname;}public void doinit(){System.out.println("方法初始化");}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("接口的初始化方法");}@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {System.out.println("BeanFactoryAware接口");}@Overridepublic void setBeanName(String s) {System.out.println("BeanNameAware接口");}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {System.out.println("ApplicationContextAware接口");} }
-
創建bean后處理類
public class MyBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("Bean的后處理的postProcessBeforeInitialization方法");return null;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("Bean的后處理的postProcessAfterInitialization方法");return null;} }
-
spring主配置文件
<?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 id="student" class="com.dong.bean.Student" init-method="doinit"><property name="sname" value="張三"></property></bean><bean id="beanPostProcessor" class="com.dong.provessor.MyBeanPostProcessor"></bean></beans>
-
測試:getBean注入的Student
public class Test01 {public static void main(String[] args) {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");Student student = (Student) applicationContext.getBean("student");System.out.println("bean的實例對象:" + student);} }
-
輸入結果,順序如下:
bean的無參構造方法
set方法賦值
BeanNameAware接口
BeanFactoryAware接口
ApplicationContextAware接口
Bean的后處理的postProcessBeforeInitialization方法
接口的初始化方法
方法初始化
Bean的后處理的postProcessAfterInitialization方法
bean的實例對象:com.li.bean.Student@6536e911