餓了麼面試官:簡歷上說你精通Spring Bean的生命週期?

前言

Spring Bean的生命週期是Spring面試熱點問題。這個問題即考察對Spring的微觀瞭解,又考察對Spring的宏觀認識,想要答好並不容易!本文但願可以從源碼角度入手,幫助面試者完全搞定Spring Bean的生命週期,如下部份內容參考Spring學習筆記,感興趣的朋友也能夠閱讀一下!面試

SpringBean的生命週期

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

流程圖以下app

餓了麼面試官:簡歷上說你精通Spring Bean的生命週期?

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

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

建立Bean對象

既然都說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,固然也能夠用註解的方式。this

<bean class="SpringBean">
     <property name="field" value="test" />
 </bean>

而後咱們去初始化這個容器看看,運行結果是什麼code

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

餓了麼面試官:簡歷上說你精通Spring Bean的生命週期?

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

重寫setBeanName方法

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

public void setBeanName(String s) {
 System.out.println("setBeanName:"+s);
 }
<bean id="BeanName" class="SpringBean">
     <property name="field" value="test" />
 </bean>

運行一下看會發生什麼

餓了麼面試官:簡歷上說你精通Spring Bean的生命週期?

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

餓了麼面試官:簡歷上說你精通Spring Bean的生命週期?

咱們能夠看到先執行的是setBeanFactory方法而後是setApplicationContext方法

建立一個新的Bean

下面咱們再建立一個新的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 class="SpringProccesserBean"></bean>

而後咱們再運行試試

餓了麼面試官:簡歷上說你精通Spring Bean的生命週期?

不出咱們所料,前置方法和後置方法依次在後面運行了,難道這就是Bean的所有了嗎?呵呵,太天真了,若是在Bean中有實現InitializingBean接口,那又是不一樣的說法了。咱們下面除了重寫了afterPropertiesSet方法之外咱們還能夠在bean裏面指定它的init方法。

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

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

不要忘記配置文件

<bean id="BeanName" class="SpringBean" init-method="init">
     <property name="field" value="test" />
 </bean>

餓了麼面試官:簡歷上說你精通Spring Bean的生命週期?

能夠看到,這兩個方法是夾在前置處理器和後置處理器之間的,先執行的是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 id="BeanName" class="SpringBean" init-method="init" destroy-method="des">
     <property name="field" value="test" />
 </bean>

這兩個方法會在關閉容易的時候調用,所以咱們調用close方法關閉容器

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

 applicationContext.close();

 }

運行結果

餓了麼面試官:簡歷上說你精通Spring Bean的生命週期?

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

這就是SpringBean的生命週期。

讀者福利:Spring boot學習筆記+面試真題

總結

Spring Bean的生命週期

一、實例化Bean對象

二、設置Bean屬性

三、若是經過各類Aware接口聲明瞭依賴關係,則會注入Bean對容器基礎設施層面的依賴。

Aware接口集體包括BeanNameAware、BeanFactoryAware和ApplicationContextAware

分別注入Bean ID、Bean Factory 和ApplicationContext

四、若是實現了BeanPostProcesser,調用BeanPostProcesser的前置初始化方法postProcessBeforeInitialization

五、若是實現了InitializingBean接口,則會調用afterPropertiesSet方法

六、調用Bean自身定義的init方法

七、調用BeanPostProcesser的後置方法postProcessAfterInitialization

建立完畢

銷燬

八、容器關閉前調用DisposableBean的destroy方法和自身的destroy方法

相關文章
相關標籤/搜索