11.29 一步一步,帶你瞭解SpringBean的生命週期



SpringBean的生命週期

在面試中,我們經常會被問到一個問題,就是SpringBean的生命週期。用大白話說,就是說其在創造到銷燬按順序調用了什麼方法,在我剛開始學了,一般就是對著標準答案去硬背,完全不瞭解其意思,也十分容易忘記。

流程圖如下

一步一步,帶你瞭解SpringBean的生命週期

這樣看上去十分的複雜,記住也很容易忘掉。

所以,我下面會用代碼的方式一步步來模擬SpringBean的工作流程,做到深入瞭解,這樣就不會再次忘記這個知識點了。

既然都說Bean對象Bean對象,那麼SpringBean自然也是一個對象了,我們用一個簡單的對象來說明,那麼要創建對象就需要有構造方法,對象還會有它的屬性跟get、set方法。

 private String field;

public SpringBean() {
System.out.println("SpringBean 構造方法");
}

public String getField() {
System.out.println("SpringBean get方法");
return field;
}

public void setField(String field) {
System.out.println("SpringBean set方法");
this.field = field;
}

眾所周知要創建一個SpringBean的話還要在配置文件裡去聲明這個Beam,當然也可以用註解的方式。

 <bean>
\t <property>
/<bean>

然後我們去初始化這個容器看看,運行結果是什麼

public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext =
new ClassPathXmlApplicationContext("spring.xml");
}
一步一步,帶你瞭解SpringBean的生命週期

這裡我們可以看到當我們在容器裡面加載bean的時候,它會依次調用構造方法和set方法,這兩步我相信大部分人都知道。但是除此之外我們想一想,我們的Spring它是否還幹了別的事情,我們接下來看一下。

如果這個Bean它實現了一些Aware接口的話,它就會注入和bean容器基礎屬性層面相關的信息。比如實現了BeanNameAware接口,我們要重寫它的setBeanName方法,在配置文件中把這個Bean的id設置一下

 public void setBeanName(String s) {
System.out.println("setBeanName:"+s);
}
<bean>
\t <property>
/<bean>

運行一下看會發生什麼

一步一步,帶你瞭解SpringBean的生命週期

剩下的BeanFactoryAware和ApplicationContextAware接口同理,我們直接看結果

一步一步,帶你瞭解SpringBean的生命週期

我們可以看到先執行的是setBeanFactory方法然後是setApplicationContext方法

下面我們再創建一個新的Bean,這個Bean是做全局的前置和後置初始化的,也就是我們看面試題時所說的前置處理器和後置處理器。

這個Bean我們實現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 null;
}

千萬不要忘記要在配置文件裡聲明這個Bean

<bean>

然後我們再運行試試

一步一步,帶你瞭解SpringBean的生命週期

不出我們所料,前置方法和後置方法依次在後面運行了,難道這就是Bean的全部了嗎?呵呵,太天真了,如果在Bean中有實現InitializingBean接口,那又是不同的說法了。我們下面除了重寫了afterPropertiesSet方法以外我們還可以在bean裡面指定它的init方法。

 public void afterPropertiesSet() throws Exception {
System.out.println("afterPropertiesSet");
}

public void init(){
System.out.println("init");
}

不要忘記配置文件

<bean>
\t <property>
/<bean>
一步一步,帶你瞭解SpringBean的生命週期

可以看到,這兩個方法是夾在前置處理器和後置處理器之間的,先執行的是InitializingBean接口的afterPropertiesSet方法然後是Bean自身的init方法。

至此,一個Bean的初始化環節就完成了,我們就可以去使用這個Bean了。

既然是說Bean的生命週期,那當然還有Bean的銷燬流程了,Bean的銷燬流程一共分為連個步驟,一個步驟是實現銷燬接口DisposableBean,重寫它的銷燬方法destroy,還有一個是Bean自身的destroy方法。

public void destroy() throws Exception {
System.out.println("DisposableBean");
}

public void des(){
System.out.println("des");
}

記得要在配置文件裡定義

<bean>
\t <property>
/<bean>

這兩個方法會在關閉容易的時候調用,因此我們調用close方法關閉容器

public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext =
new ClassPathXmlApplicationContext("spring.xml");

applicationContext.close();

}

運行結果

一步一步,帶你瞭解SpringBean的生命週期

我們看到是先調用DisposableBean接口的destroy方法然後是Bean自身的銷燬方法。

這就是SpringBean的生命週期。

下面我們來總結一下

Spring Bean的生命週期

 1、實例化Bean對象
2、設置Bean屬性
3、如果通過各種Aware接口聲明瞭依賴關係,則會注入Bean對容器基礎設施層面的依賴。
Aware接口集體包括BeanNameAware、BeanFactoryAware和ApplicationContextAware
分別注入Bean ID、Bean Factory 和ApplicationContext
4、如果實現了BeanPostProcesser,調用BeanPostProcesser的前置初始化方法postProcessBeforeInitialization
5、如果實現了InitializingBean接口,則會調用afterPropertiesSet方法
6、調用Bean自身定義的init方法
7、調用BeanPostProcesser的後置方法postProcessAfterInitialization
創建完畢
銷燬
8、容器關閉前調用DisposableBean的destroy方法和自身的destroy方法



分享到:


相關文章: