淺談spring bean生命週期

關於spring bean的生命週期,是深入學習spring的基礎,也是難點,本篇文章將採用代碼+圖文結論的方式來闡述spring bean的生命週期,本篇文章將闡述清楚下圖。

一  項目結構及源碼

1.程序目錄結構

 2.applicationContext.xml

複製代碼

<?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 class="com.demo.dao.UserDao" id="userDao" scope="singleton" init-method="myInit" destroy-method="myDestroy">
        <property name="userName" value="Alan_beijing"/>
    </bean>

    <bean class="com.demo.dao.MyBeanPostProcessor" id="myBeanPostProcessor"/>

</beans>

複製代碼

3.UserDao.java

複製代碼

package com.demo.dao;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.apache.log4j.Logger;

public class UserDao implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean,
        DisposableBean{

    private String userName;
    private int count = 0;

    public String getUserName() {
        return userName;
    }

    //2.屬性注入,注入屬性爲userName
    public void setUserName(String userName) {
        count++;
        System.out.println(count + ":注入屬性userName="+userName);
        this.userName = userName;
    }

    //1.無參構造函數,實例化時調用該構造函數
    public UserDao() {
        count++;
        System.out.println(count + ":調用構造函數UserDao()");
    }

    //3.實現BeanNameAware,獲取bean id
    public void setBeanName(String s) {
        count++;
        System.out.println(count + ":調用setBeanName()獲取bean id,bean id=" + s);
    }

    //4.實現BeanFactoryAware,獲取bean工廠
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        count++;
        System.out.println(count + ":調用setBeanFactory()獲取bean工廠,beanFactory=" + beanFactory);
    }

    //5.實現ApplicationContextAware,獲取bean上下文
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        count++;
        System.out.println(count + ":調用setApplicationContext()獲取bean上下文,applicationContext=" + applicationContext);
    }

    //6.實現InitializingBean,獲取afterPropertiesSet
    public void afterPropertiesSet() throws Exception {
        count++;
        System.out.println(count + ":調用afterPropertiesSet()");
    }

    //7.自定義初始化方法myInit()
    public void myInit() {
        count++;
        System.out.println(count + ":調用自定義myInit()");
    }

    //8.實現DisposableBean,獲取destroy()
    public void destroy() throws Exception {
        count++;
        System.out.println(count + ":destroy()");
    }

    //9.自定義銷燬方法myDestroy()
    public void myDestroy() {
        count++;
        System.out.println(count + ":調用自定義destroy()");
    }
}

複製代碼

4.MyBeanPostProcessor.java

複製代碼

package com.demo.dao;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public  class MyBeanPostProcessor implements 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 bean;
    }
}

複製代碼

 二  測試代碼及測試結果

1.test.java

複製代碼

package com.demo.test;

import com.demo.dao.UserDao;
import org.junit.Test;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {

    @Test
    public void test() {
        //定義容器並初始化
        //ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        applicationContext.getBean(UserDao.class);
        //只有關閉容器時,纔會調用destroy方法
        applicationContext.registerShutdownHook();
    }
}

複製代碼

2.測試結果

 三 分析

通過如上測試結果,bean生命週期流程大致如下:

 

 1.裝配bean

bean裝配爲bean生命週期第一環節。所謂裝配bean,指將java對象轉換爲bean的過程。在該示例中,UserDao.jave和MyBeanPostProcessor通過xml方式轉化爲bean。

注意:spring框架支持四種方式裝配bean:xml方式,java代碼方式,自動裝配和混合裝配方式

2.加載applicationContext.xml並實例化

加載並實例化bean爲bean生命週期的第二環節。本文示例通過ClassPathXmlApplicationContext()來加載並,當bean爲singleton時,該過程就實例化對象,而不需要等待

調用applicationContext.getBean()獲取bean時才實例化對象,這與prototype是不一樣的。

3.屬性注入

bean屬性注入爲bean生命週期第三環節,採用反射方式注入bean.

 

4.實現BeanNameAware,獲取bean id

該過程爲bean生命週期的第四環節,實現該接口,可以獲取bean的id

 

5.實現BeanFactoryAware,獲取bean 工廠

該過程爲bean生命週期第五環節,通過實現BeanFactoryAware獲取bean工廠

 6.實現ApplicationContextAware,獲取運用上下文

該過程爲bean生命週期第六環節,通過實現ApplicationContextAware接口,獲取bean上下文

 7.調用Bean後置處理器,before

該過程爲bean生命週期第七環節,通過實現後置處理器BeanPostProcessor獲取before和after,該過程是通過AOP方式實現的,在before和after之間,發生如下8,9過程。

8.實現InitializingBean的afterPropertiesSet(),獲取初始化方法

該過程爲bean生命週期第八環節,通過實現InitializingBean,獲取afterPropertiesSet()

 9.調用自定義初始化方法,init-method

該過程爲bean生命週期第九環節,實現自定義初始化方法

 10.調用Bean後置處理器after

該過程爲bean生命週期第十環節,後置處理器最後環節

 11.關閉容器AbstractApplicationContext.registerShutDownHook()

該環節爲bean生命週期第十一環節,關閉容器

 

 12.調用DisposableBean的destroy()

該過程爲bean生命週期第十二環節,實現DisposableBean接口,調用destroy()

 13.調用定製化銷燬方法destroy-method

該過程爲bean生命週期最後環節,調用自定義銷燬方法destroy-method

 三  版權區

  •   轉載博客,必須註明博客出處
  •    博主網址:http://www.cnblogs.com/wangjiming/
  •    如您有新想法,歡迎提出,郵箱:[email protected]
  •   專業.NET之家技術QQ羣:490539956
  •   專業化Java之家QQ羣:924412846
  •   有問必答QQ羣:2098469527
  •   一對一技術輔導QQ:2098469527
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章