1. 程式人生 > >Spring Bean生命週期詳解

Spring Bean生命週期詳解

  在Spring中 Bean 可謂是一個核心的元素,當我們結合Spring進行程式設計的時候也離不開Bean,面對這樣重要的一個角色,瞭解其生命週期和該生命週期所涉及的環節對我們更加熟練靈活地使用Bean是很有Bean必要的,下面我們就來詳細分析下Bean的生命週期吧。

生命週期流程圖

  我們先通過一個流程圖,對Bean的生命週期先做一個整體的認識和了解。 這裡寫圖片描述   若容器實現了流程圖中涉及的介面,程式將按照以上流程進行。需要我們注意的是,這些介面並不是必須實現的,可根據自己開發中的需要靈活地進行選擇,沒有實現相關介面時,將略去流程圖中的相關步驟。

介面方法的分類

  上面流程圖當中涉及呼叫很多的方法,可能我們直接去理解和記憶比較困難,其實對於這麼一大堆方法我們可以根據它們的特點對他們進行整理分類,下面提供一種可供大家參考的分類模型:

分類型別 所包含方法
Bean自身的方法 配置檔案中的init-method和destroy-method配置的方法、Bean物件自己呼叫的方法
Bean級生命週期介面方法 BeanNameAware、BeanFactoryAware、InitializingBean、DiposableBean等介面中的方法
容器級生命週期介面方法 InstantiationAwareBeanPostProcessor、BeanPostProcessor等後置處理器實現類中重寫的方法

  這時回過頭再來看這些方法輪廓上就比較清晰了,記憶的時候我們可通過記憶分類的型別來理解性的記憶所涉及的方法。

程式設計實踐

  有了上面的理論分析,我們再來通過程式設計實踐來驗證下我們的結論,順便進一步加深我們對整個生命週期的理解。

準備工作

編寫測試Bean

  我們先編寫一個測試Bean來實現流程圖中的相關介面.    StudentBean.java

package com.yanxiao.cyclelife;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import
org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; /** * 測試生命週期的Bean * Created by yanxiao on 2016/8/1. */ public class StudentBean implements InitializingBean, DisposableBean, BeanNameAware, BeanFactoryAware { private String name; private int age; private String beanName;//實現了BeanNameAware介面,Spring可以將BeanName注入該屬性中 private BeanFactory beanFactory;//實現了BeanFactory介面,Spring可將BeanFactory注入該屬性中 public StudentBean(){ System.out.println("【Bean構造方法】學生類的無參構造方法"); } @Override public String toString() { return "StudentBean{" + "name='" + name + '\'' + ", age=" + age + ", beanName='" + beanName + '\'' + '}'; } public String getName() { return name; } public void setName(String name) { System.out.println("【set注入】注入學生的name屬性"); this.name = name; } public int getAge() { return age; } public void setAge(int age) { System.out.println("【set注入】注入學生的age屬性"); this.age = age; } /** * 自己編寫的初始化方法 */ public void myInit(){ System.out.println("【init-method】呼叫init-method屬性配置的初始化方法"); } /** * 自己編寫的銷燬方法 */ public void myDestroy(){ System.out.println("【destroy-method】呼叫destroy-method屬性配置的銷燬方法"); } /** * BeanFactoryAware介面的方法 * @param beanFactory * @throws BeansException */ @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; System.out.println("【BeanFactoryAware介面】呼叫BeanFactoryAware的setBeanFactory方法得到beanFactory引用"); } /** * BeanNameAware介面的方法 * @param name */ @Override public void setBeanName(String name) { this.beanName = name; System.out.println("【BeanNameAware介面】呼叫BeanNameAware的setBeanName方法得到Bean的名稱"); } /** * InitializingBean介面的方法 * @throws Exception */ @Override public void afterPropertiesSet() throws Exception { System.out.println("【InitializingBean介面】呼叫InitializingBean介面的afterPropertiesSet方法"); } /** * DisposableBean介面的方法 * @throws Exception */ @Override public void destroy() throws Exception { System.out.println("【DisposableBean介面】呼叫DisposableBean介面的destroy方法"); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105

  上面程式碼中的 myInit() 和 ·myDestroy()· 方法供我們在配置檔案中通過init-method和destroy-method屬性進行指定。

實現BeanPostProcessor介面

  我們編寫BeanPostProcessor介面的一個實現類: MyBeanPostProcessor.java

package com.yanxiao.cyclelife;

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

/**
 * Created by yanxiao on 2016/8/1.
 */
public class MyBeanPostProcessor implements BeanPostProcessor {

    public MyBeanPostProcessor(){
        System.out.println("【BeanPostProcessor介面】呼叫BeanPostProcessor的構造方法");
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("【BeanPostProcessor介面】呼叫postProcessBeforeInitialization方法,這裡可對"+beanName+"的屬性進行更改。");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("【BeanPostProcessor介面】呼叫postProcessAfterInitialization方法,這裡可對"+beanName+"的屬性進行更改。");
        return bean;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

實現BeanPostProcessor介面

  編寫BeanPostProcessor介面的一個實現類 MyBeanPostProcessor.java

package com.yanxiao.cyclelife;

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

/**
 * Created by yanxiao on 2016/8/1.
 */
public class MyBeanPostProcessor implements BeanPostProcessor {

    public MyBeanPostProcessor(){
        System.out.println("【BeanPostProcessor介面】呼叫BeanPostProcessor的構造方法");
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("【BeanPostProcessor介面】呼叫postProcessBeforeInitialization方法,這裡可對"+beanName+"的屬性進行更改。");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("【BeanPostProcessor介面】呼叫postProcessAfterInitialization方法,這裡可對"+beanName+"的屬性進行更改。");
        return bean;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

實現InstantiationAwareBeanPostProcessor介面

  實現InstantiationAwareBeanPostProcessor介面,為了程式設計方便我們直接通過繼承Spring中已經提供的一個實現了該介面的介面卡類InstantiationAwareBeanPostProcessorAdapter來進行測試。

MyInstantiationAwareBeanPostProcessor.java

package com.yanxiao.cyclelife;

import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;

import java.beans.PropertyDescriptor;

/**
 * 一般情況下,當我們需要實現InstantiationAwareBeanPostProcessor介面時,是通過繼承Spring框架中InstantiationAwareBeanPostProcessor介面實現類
 * InstantiationAwareBeanPostProcessorAdapter這個介面卡類來簡化我們實現介面的工作
 * Created by yanxiao on 2016/8/1.
 */
public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {

    public MyInstantiationAwareBeanPostProcessor() {
        System.out.println("【InstantiationAwareBeanPostProcessor介面】呼叫InstantiationAwareBeanPostProcessor構造方法");
    }

    /**
     * 例項化Bean之前呼叫
    */
    @Override
    public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {
        System.out.println("【InstantiationAwareBeanPostProcessor介面】呼叫InstantiationAwareBeanPostProcessor介面的postProcessBeforeInstantiation方法");
        return ;
    }

    /**
     * 例項化Bean之後呼叫
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("【InstantiationAwareBeanPostProcessor介面】呼叫InstantiationAwareBeanPostProcessor介面的postProcessAfterInitialization方法");
        return bean;
    }

    /**
     * 設定某個屬性時呼叫
     */
    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
            throws BeansException {
        System.out.println("【InstantiationAwareBeanPostProcessor介面】呼叫InstantiationAwareBeanPostProcessor介面的postProcessPropertyValues方法");
        return pvs;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

BeanFactoryPostProcessor介面

  我們編寫BeanFactoryPostProcessor介面的一個實現類 BeanFactoryPostProcessor.java

package com.yanxiao.cyclelife;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

/**
 * Created by yanxiao on 2016/8/1.
 */
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    public MyBeanFactoryPostProcessor() {
        System.out.println("【BeanFactoryPostProcessor介面】呼叫BeanFactoryPostProcessor實現類構造方法");
    }

    /**
     * 重寫BeanFactoryPostProcessor介面的postProcessBeanFactory方法,可通過該方法對beanFactory進行設定
     */
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
            throws BeansException {
        System.out.println("【BeanFactoryPostProcessor介面】呼叫BeanFactoryPostProcessor介面的postProcessBeanFactory方法");
        BeanDefinition beanDefinition = beanFactory.getBeanDefinition("studentBean");
        beanDefinition.getPropertyValues().addPropertyValue("age", "21");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

編寫Spring配置檔案beans.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" xmlns:p="http://www.springframework.org/schema/p"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">

    <!--配置Bean的後置處理器-->
    <bean id="beanPostProcessor" class="com.yanxiao.cyclelife.MyBeanPostProcessor">
    </bean>

    <!--配置instantiationAwareBeanPostProcessor-->
    <bean id="instantiationAwareBeanPostProcessor" class="com.yanxiao.cyclelife.MyInstantiationAwareBeanPostProcessor">
    </bean>

    <!--配置BeanFactory的後置處理器-->
    <bean id="beanFactoryPostProcessor" class="com.yanxiao.cyclelife.MyBeanFactoryPostProcessor">
    </bean>

    <bean id="studentBean" class="com.yanxiao.cyclelife.StudentBean" init-method="myInit"
          destroy-method="myDestroy" scope="singleton">
        <property name="name" value="yanxiao"></property>
        <property name="age" value="21"></property>
    </bean>

</beans>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

進行測試

  通過上面的準備工作我們已經把相關的類和測試檔案編寫完畢,下面我們就通過測試程式碼來驗證我們的成果。

package com.yanxiao.cyclelife;


import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Created by yanxiao on 2016/8/1.
 */
public class TestCyclelife {

    public static void main(String[] args){
        System.out.println("--------------【初始化容器】---------------");

        ApplicationContext context = new ClassPathXmlApplicationContext("META-INF/beans1.xml");
        System.out.println("-------------------【容器初始化成功】------------------");
        //得到studentBean,並顯示其資訊
        StudentBean studentBean = context.getBean("studentBean",StudentBean.class);
        System.out.println(studentBean);

        System.out.println("--------------------【銷燬容器】----------------------");
        ((ClassPathXmlApplicationContext)context).registerShutdownHook();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

測試結果

這裡寫圖片描述   執行結果符合我們預期,成功驗證之前的結論。