Spring教程-Spring Bean的生命週期

Ricky_Fung發表於2016-12-18

理解 Spring bean 的生命週期很容易。當一個 bean 被例項化時,它可能需要執行一些初始化使它轉換成可用狀態。同樣,當 bean 不再需要,並且從容器中移除時,可能需要做一些清除工作。

Bean的完整生命週期經歷了各種方法呼叫,這些方法可以劃分為以下幾類:

  1. Bean自身的方法:這個包括了Bean本身呼叫的方法和通過配置檔案中<bean>的init-method和destroy-method指定的方法
  2. Bean生命週期回撥介面方法:這個包括了BeanNameAware、BeanFactoryAware、ApplicationContextAware、InitializingBean和DiposableBean這些介面的方法
  3. 容器級生命週期介面方法:這個包括了BeanPostProcessor 和BeanFactoryPostProcessor 這兩個介面實現,一般稱它們的實現類為“後處理器”。


本文講解均基於 Spring Framework 4.3.3.RELEASE

Bean初始化回撥

org.springframework.beans.factory.InitializingBean 介面指定一個單一的方法:

void afterPropertiesSet() throws Exception;

因此,你可以簡單地實現上述介面和初始化工作可以在 afterPropertiesSet() 方法中執行,如下所示:

public class ExampleBean implements InitializingBean {
   public void afterPropertiesSet() throws Exception {
      // do some initialization work
   }
}

在基於 XML 的配置後設資料的情況下,你可以使用 init-method 屬性來指定帶有 void 無引數方法的名稱。例如:

<bean id="exampleBean" 
         class="examples.ExampleBean" init-method="init"/>

下面是ExampleBean 類的定義:

public class ExampleBean {
   public void init() {
      // do some initialization work
   }
}

Bean銷燬回撥

org.springframework.beans.factory.DisposableBean 介面指定一個單一的方法:

void destroy() throws Exception;

因此,你可以簡單地實現上述介面並且結束工作可以在 destroy() 方法中執行,如下所示:

public class ExampleBean implements DisposableBean {
   public void destroy() throws Exception {
      // do some destruction work
   }
}

在基於 XML 的配置後設資料的情況下,你可以使用 destroy-method 屬性來指定帶有 void 無引數方法的名稱。例如:

<bean id="exampleBean"
         class="examples.ExampleBean" destroy-method="destroy"/>

下面是ExampleBean 類的定義:

public class ExampleBean {
   public void destroy() {
      // do some destruction work
   }
}

示例

下面通過一個簡單的Spring Bean來演示Bean的生命週期,程式碼如下:

package com.bytebeats.spring.lifecycle;

/**
 * ${DESCRIPTION}
 *
 * @author Ricky Fung
 * @create 2016-12-28 22:46
 */
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;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
 * ${DESCRIPTION}
 *
 * @author Ricky Fung
 * @create 2016-12-28 22:44
 */
public class ExampleBean implements BeanFactoryAware, BeanNameAware, ApplicationContextAware,
        InitializingBean, DisposableBean {

    private BeanFactory beanFactory;
    private String beanName;
    private ApplicationContext applicationContext;

    public ExampleBean() {
        System.out.println("【構造器】呼叫Person的構造器例項化");
    }

    // 這是BeanFactoryAware介面方法
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out
                .println("【BeanFactoryAware介面】呼叫BeanFactoryAware.setBeanFactory()");
        this.beanFactory = beanFactory;
    }

    // 這是BeanNameAware介面方法
    @Override
    public void setBeanName(String beanName) {
        System.out.println("【BeanNameAware介面】呼叫BeanNameAware.setBeanName()");
        this.beanName = beanName;
    }

    // 這是ApplicationContextAware介面方法
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("【ApplicationContextAware介面】呼叫ApplicationContextAware.setApplicationContext()");
        this.applicationContext = applicationContext;
    }

    // 這是InitializingBean介面方法
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("【InitializingBean介面】呼叫InitializingBean.afterPropertiesSet()");
    }

    // 這是DiposibleBean介面方法
    @Override
    public void destroy() throws Exception {
        System.out.println("【DiposibleBean介面】呼叫DiposibleBean.destory()");
    }

    // 通過<bean>的init-method屬性指定的初始化方法
    public void initMethod() {
        System.out.println("【init-method】呼叫<bean>的init-method屬性指定的初始化方法");
    }

    // 通過<bean>的destroy-method屬性指定的初始化方法
    public void destroyMethod() {
        System.out.println("【destroy-method】呼叫<bean>的destroy-method屬性指定的初始化方法");
    }

}


配置檔案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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <context:annotation-config/>
    <context:component-scan base-package="com.bytebeats.spring.lifecycle"/>

    <bean id="exampleBean" class="com.bytebeats.spring.lifecycle.ExampleBean" init-method="initMethod"
          destroy-method="destroyMethod" scope="singleton"/>

</beans>


測試類如下:

public class App {

    public static void main(String[] args) {

        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        System.out.println("Spring容器初始化成功");

        ExampleBean exampleBean = (ExampleBean) context.getBean("exampleBean");
        System.out.println(exampleBean);

        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Spring容器開始關閉");
        context.close();
    }
}


執行結果如下:

十二月 28, 2016 11:06:31 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
資訊: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@4e1557af: startup date [Wed Dec 28 23:06:31 CST 2016]; root of context hierarchy
十二月 28, 2016 11:06:31 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
資訊: Loading XML bean definitions from class path resource [applicationContext.xml]
【構造器】呼叫Person的構造器例項化
【BeanNameAware介面】呼叫BeanNameAware.setBeanName()
【BeanFactoryAware介面】呼叫BeanFactoryAware.setBeanFactory()
【ApplicationContextAware介面】呼叫ApplicationContextAware.setApplicationContext()
【InitializingBean介面】呼叫InitializingBean.afterPropertiesSet()
【init-method】呼叫<bean>的init-method屬性指定的初始化方法
Spring容器初始化成功
com.bytebeats.spring.lifecycle.ExampleBean@390f9eb5
Spring容器開始關閉
十二月 28, 2016 11:06:36 下午 org.springframework.context.support.ClassPathXmlApplicationContext doClose
資訊: Closing org.springframework.context.support.ClassPathXmlApplicationContext@4e1557af: startup date [Wed Dec 28 23:06:31 CST 2016]; root of context hierarchy
【DiposibleBean介面】呼叫DiposibleBean.destory()
【destroy-method】呼叫<bean>的destroy-method屬性指定的初始化方法

相關文章