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

測試結果

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章