一個Bean從生到滅要經歷很多過程,總體分爲定義、實例化、屬性賦值(依賴注入)、初始化、生存期、銷燬。
如下圖,是個概括圖,後面重點介紹Bean的定義、初始化、銷燬過程:
下面是一個細化的Bean生命週期圖:
一、Bean的定義
Bean的定義過程其實就是如何正確地將 Bean 裝配到 IoC 容器中。
- Spring通過我們的配置,如@ComponentScan定義的掃描路徑去找到帶有@Component的類,完成資源定位的過程
一旦找到了資源,那麼它就開始解析,並且將定義的信息在BeanDefinition的實現類中保存起來 。注意,此時還沒有初始Bean,也就沒有Bean實例,它有的僅僅是 Bean 定義。 然後就會把 Bean 定義發佈到 Spring IoC 容器中。此時,IoC 容器也只有 Bean 的定義,還是沒有 Bean的實例生成。
BeanDefinition的實現類可以保存這個bean的構造函數參數、bean的Scope範圍、是否是延遲初始化LazyInit、是否是Singleton等信息。
二、Bean的初始化
三、代碼驗證
我們還是用人類要喫飯的關係類說明Bean的生命週期。先實現Person和Food兩個接口:
public interface Person {
public void live();
public void setFood(Food food);
}
public interface Food {
public void eat();
}
接着編寫上面兩個接口的實現類:
@Component
public class Apple implements Food {
@Override
public void eat() {
System.out.println("我是蘋果,喫我吧");
}
}
public class ZhangSan implements Person, BeanNameAware, BeanFactoryAware,
ApplicationContextAware, InitializingBean, DisposableBean {
private Food food = null;
/**
* 來自Person接口
*/
@Override
public void live() {
this.food.eat();
}
/**
* 來自Person接口
*/
@Override
public void setFood(Food food) {
System.out.println("設置 food !");
this.food = food;
}
/**
* 來自BeanNameAware接口
*/
@Override
public void setBeanName(String beanName) {
System.out.println("【" + this.getClass().getSimpleName() + "】調用BeanNameAware的setBeanName");
}
/**
* 來自BeanFactoryAware接口
*/
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("【" + this.getClass().getSimpleName() + "】調用BeanFactoryAware的setBeanFactory");
}
/**
* 來自BApplicationContextAware接口
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("【" + this.getClass().getSimpleName() + "】調用ApplicationContextAware的setApplicationContext");
}
/**
* 來自InitializingBean接口
*/
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("【" + this.getClass().getSimpleName() + "】調用InitializingBean的afterPropertiesSet");
}
@PostConstruct
public void init() {
System.out.println("【" + this.getClass().getSimpleName() + "】註解@Postconstruct定義的自定義初始化方法");
}
@PreDestroy
public void destroy1() {
System.out.println("【" + this.getClass().getSimpleName() + "】註解@PreDestroy定義的自定義銷燬方法");
}
/**
* 來自DisposableBean接口
*/
@Override
public void destroy() throws Exception {
System.out.println("【" + this.getClass().getSimpleName() + "】調用DisposableBean方法");
}
}
上面我們讓ZhangSan實現了多個初始化需要的接口,並實現了相應的方法,來完成ZhangSan這個bean的初始化處理,爲了說明自定義初始化方法,我們使用@PostConstruct註解增加了自定義初始化過程,爲了說明自定義銷燬方法我們使用@PreDestroy增加了自定義銷燬過程,另外爲了說明BeanPostProcessor接口是針對全部bean的,下面實現了這個接口:
public class BeanPostProcessorExample implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor調用postProcessBeforeInitialization參數【" + bean.getClass().getSimpleName()+"】【" + beanName + "】");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor調用postProcessAfterInitialization參數【" + bean.getClass().getSimpleName()+"】【" + beanName + "】");
return bean;
}
}
然後我們用一個類聚合下上面的bean:
@Configuration
public class Config {
@Bean
public ZhangSan initZhangSan(){
ZhangSan zhangSan = new ZhangSan();
zhangSan.setFood(new Apple());
return zhangSan;
}
@Bean
public BeanPostProcessorExample initExample(){
return new BeanPostProcessorExample();
}
}
測試類:
@SpringBootTest
class GfdemoApplicationTests {
@Test
void contextLoads() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);
ctx.close();
}
}
結果:
BeanPostProcessor調用postProcessBeforeInitialization參數【Apple】【apple】
BeanPostProcessor調用postProcessAfterInitialization參數【Apple】【apple】
設置 food !
【ZhangSan】調用BeanNameAware的setBeanName
【ZhangSan】調用BeanFactoryAware的setBeanFactory
【ZhangSan】調用ApplicationContextAware的setApplicationContext
BeanPostProcessor調用postProcessBeforeInitialization參數【ZhangSan】【initZhangSan】
【ZhangSan】註解@Postconstruct定義的自定義初始化方法
【ZhangSan】調用InitializingBean的afterPropertiesSet
BeanPostProcessor調用postProcessAfterInitialization參數【ZhangSan】【initZhangSan】
【ZhangSan】註解@PreDestroy定義的自定義銷燬方法
【ZhangSan】調用DisposableBean方法
可以看出bean的生命週期流程是按照上面的圖進行的,另外也可以看出BeanPostProcessor接口是針對全部bean的,在初始化Apple和ZhangSan的時候都有執行。