Spring容器中bean的生命週期
1、Spring生命週期
-
所謂生命週期就是一個對象從初始化到銷燬的過程,在Spring容器中bean的生命週期可以總結爲:
- 初始化(實例化);
- 屬性注入(我們平時new對象還不是一樣要set屬性);
- 如果bean實現BeanNameAuthorware接口,則執行setBeanName的方法(作用是給bean設置一個獨有的id方面我們獲取實例並使用);
- 如果bean實現了BeanFactoryAware接口,spring將會調用setBeanFactory()方法將BeanFactory容器傳入;
- 如果bean實現了ApplicationContextAware接口,spring將調用setApplication()方法,將bean所在的應用上下文的引用傳入進來;
- 如果bean實現了BeanPostProcessor接口,Spring將調用所有bean的postProcessBeforeInitialization()方法;
- 如果bean實現了InitializingBean接口,spring將調用它們的afterPropertiesSet()方法,類似的,如果bean使用init-method聲明瞭初始化方法,該方法也會調用,或者使用註解@PostConstruct都一樣的效果。
- 跟第6條對應,同樣的接口 ,調用所有bean的postProcessAfterInitialization()方法
- 調用@PreDestroy標註的方法;
- 如果bean實現接DisposableBean接口,會調用它的destroy()方法
-
圖解
在這裏安利一本書:spring實戰第四版,這個圖就跟書上的一模一樣,看完了個人感覺對於spring的理解非常到位(個人感覺前面的幾章寫得非常好)
2、演示bean生命週期
- 搭建一個springboot項目(spring或者springboot都可以演示,主要是用了springboot就不會再想玩spring了)
- 寫三個類:
- TestBean:
package com.example.demo.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import javax.annotation.PreDestroy;
public class TestBean implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean {
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("執行了:setBeanFactory");
}
@Override
public void setBeanName(String s) {
System.out.println("執行了:setBeanName");
}
@Override
public void destroy() throws Exception {
System.out.println("執行了:destroy");
}
@PreDestroy
public void annodestroy(){
System.out.println("執行了:@PreDestroy標註的方法");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("執行了:afterPropertiesSet");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("執行了:setApplicationContext");
}
}
太長了?其實大部分都不用看,只用看實現了什麼接口,對照着圖看就好了,實際自己寫起來理解也很方便。
- TestPostProcessorBean:
package com.example.demo.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class TestPostProcessorBean implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("執行了:postProcessBeforeInitialization");
return null;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("執行了:postProcessAfterInitialization");
return null;
}
}
這裏要注意,BeanPostProcessor接口的兩個方法所有的bean都會執行的,這裏爲什麼要單獨拎出來,BeanPostProcessor類是爲了讓創建其他類的時候進行創建前後的一些操作,如果寫在TestBean上實現的話一般是不會調用postProcessBeforeInitialization()和postProcessAfterInitialization()方法的。原因就是,在容器初始化定義的bean創建之前,容器會自己去查找所有的BeanPostProcessor進行創建自定義的類,由於是實現了BeanPostProcessor接口,因此這時候會進行BeanPostProcessor的創建和註冊,源碼中,在註冊BeanPostProcessor會進行getBean操作,即創建自定義的bean。由於默認的是單例模式,因此後面再次進行獲取就不會再次調用postProcessBeforeInitialization()和postProcessAfterInitialization()方法,因爲已經放入了spring緩存,直接獲取,不需要實例,因此沒有調用。
- TestConfig:
package com.example.demo.config;
import com.example.demo.bean.TestBean;
import com.example.demo.bean.TestPostProcessorBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class TestConfig {
@Bean("TestBean")
public TestBean getTestBean(){
return new TestBean();
}
@Bean("TestPostProcessorBean")
public TestPostProcessorBean getPostProcessorBean(){
return new TestPostProcessorBean();
}
}
3、代碼測試
package com.example.demo;
import com.example.demo.bean.TestBean;
import com.example.demo.config.TestConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TestMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext ap=new AnnotationConfigApplicationContext(TestConfig.class);
ap.getBean("TestBean", TestBean.class);
ap.close();
}
}
結果:
注意main方法要記得銷燬上下文哦,不然destroy方法是走不到的