在 Spring 中,我們可以從兩個(gè)層面定義 Bean 的生命周期:
- Bean 的作用范圍。
- 實(shí)例化 Bean 時(shí)所經(jīng)歷的一系列階段 。
1 BeanFactory 中 Bean 的生命周期
1.1 生命周期過(guò)程

過(guò)程如下:
- 當(dāng)調(diào)用者通過(guò) getBean(beanName) 向容器請(qǐng)求某一個(gè) Bean 時(shí),如果容器注冊(cè)了
org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor接口,則在實(shí)例化 Bean 之前,將調(diào)用接口的 postProcessBeforeInstantiation() 方法; - 根據(jù)配置情況調(diào)用 Bean 構(gòu)造函數(shù)或工廠方法實(shí)例化 Bean;
- 如果容器注冊(cè)了 InstantiationAwareBeanPostProcessor 接口,那么在實(shí)例化 Bean 之后,會(huì)調(diào)用該接口的 postProcessAfterInstantiation() 方法,對(duì)已經(jīng)實(shí)例化的對(duì)象進(jìn)行加工處理;
- 如果 Bean 配置了屬性信息,容器將在這一步著手將配置值設(shè)置到 Bean 對(duì)應(yīng)的屬性中,不過(guò)在設(shè)置每個(gè)屬性之前將先調(diào)用 InstantiationAwareBeanPostProcessor 接口的 postProcessPropertyValues() 方法;
- 調(diào)用 Bean 的屬性設(shè)置方法設(shè)置屬性值;
- 如果 Bean 實(shí)現(xiàn)了
org.springframework.beans.factory.BeanNameAware接口,將調(diào)用 setBeanName() 接口方法,將配置文件中該 Bean 對(duì)應(yīng)的名稱(chēng)設(shè)置到 Bean 中; - 如果 Bean 實(shí)現(xiàn)了
org.springframework.beans.factory.BeanFactoryAware接口,則將調(diào)用 setBeanFactory() 接口方法,將 BeanFactory 容器實(shí)例設(shè)置到 Bean 中; - 如果 BeanFactory 裝配了 org.springframework.beans.factory.config.BeanPostProcessor 后處理器,將調(diào)用 BeanPostProcessor 的
Object postProcessBeforeInitialization(Object bean, String beanName)接口方法對(duì) Bean 進(jìn)行加工操作 。 其中入?yún)?bean 是當(dāng)前正在處理的 Bean ,而 beanName 是當(dāng)前 Bean 的配置名,返回的對(duì)象為加工處理后的 Bean。 - 如果 Bean 實(shí)現(xiàn)了 InitializingBean 的接口,將調(diào)用接口的 afterPropertiesSet() 方法;
- 如果在 <bean> 通過(guò) init-method 屬性定義了初始化方法,將執(zhí)行這個(gè)方法;
- BeanPostProcessor 后處理器定義了兩個(gè)方法:其一是
postProcessBeforeInitialization(),它在第 8 步被調(diào)用;其二是Object postProcessAfterInitialization(Object bean, String beanName)方法,這個(gè)方法在此時(shí)被調(diào)用,可以再次對(duì) Bean 進(jìn)行加工處理; - 如果在 <bean> 中指定 Bean 的作用范圍為
scope="prototype",則將 Bean 返回給調(diào)用者,由調(diào)用者負(fù)責(zé) Bean 后續(xù)生命的管理 。 如果作用范圍設(shè)置為scope="singleton",則將 Bean 放入到 Spring IoC 容器的緩存池中,并將 Bean 的引用返回給調(diào)用者, Spring 繼續(xù)對(duì)這些 Bean 進(jìn)行后續(xù)的生命管理; - 對(duì)于
scope="singleton"的 Bean ,當(dāng)容器關(guān)閉時(shí),將觸發(fā) Spring 對(duì) Bean 的后續(xù)生命周期的管理工作,如果 Bean 實(shí)現(xiàn)了 DisposableBean 接口,則將調(diào)用接口的afterPropertiesSet()方法,可以在此編寫(xiě)釋放資源 、 記錄日志等操作; - 對(duì)于
scope="singleton"的 Bean ,如果通過(guò) <bean> 的 destroy-method 屬性指定了 Bean 的銷(xiāo)毀方法, Spring 將執(zhí)行 Bean 的這個(gè)方法,完成 Bean 資源的釋放等操作 。
Bean 的完整生命周期從 Spring 容器著手實(shí)例化 Bean 開(kāi)始,直到最終銷(xiāo)毀 Bean ,這當(dāng)中經(jīng)過(guò)了許多關(guān)鍵點(diǎn),每個(gè)關(guān)鍵點(diǎn)都涉及特定的方法調(diào)用,可以將這些方法大致劃分為 4 類(lèi):
- Bean 自身的方法:如調(diào)用 Bean 構(gòu)造函數(shù)實(shí)例化 Bean、調(diào)用 Setter 設(shè)置 Bean 的屬性值以及通過(guò)
<bean>的init-method和destroy-method所指定的方法; - Bean 級(jí)生命周期接口方法:如
BeanNameAware、BeanFactoryAware、InitializingBean和DisposableBean,這些接口方法由 Bean 類(lèi)直接實(shí)現(xiàn); - 容器級(jí)生命周期接口方法:在上圖中帶 "錨" 的步驟是由
InstantiationAwareBeanPostProcessor和BeanPostProcessor這兩個(gè)接口實(shí)現(xiàn)的,一般稱(chēng)它們的實(shí)現(xiàn)類(lèi)為 “后處理器”。 后處理器接口一般不由 Bean 本身實(shí)現(xiàn),它們獨(dú)立于 Bean ,實(shí)現(xiàn)類(lèi)以容器附加裝置的形式注冊(cè)到 Spring 容器中并通過(guò)接口反射被 Spring 容器識(shí)別 。 當(dāng) Spring 容器創(chuàng)建 Bean 時(shí),這些后處理器都會(huì)發(fā)生作用,所以這些后處理器的影響是全局性的 。 當(dāng)然,用戶(hù)也可以通過(guò)合理地編寫(xiě)后處理器,讓其僅對(duì)感興趣 Bean 進(jìn)行加工處理 。 - 工廠后處理接口方法:包括
AspectJWeavingEanbler、CustomAutowireConfigurer、ConfigurationClassPostProcessor等方法。它們也是容器級(jí)的方法,會(huì)在應(yīng)用上下文裝配好配置文件后,被立即調(diào)用。
Bean 級(jí)生命周期接口和容器級(jí)生命周期接口是個(gè)性和共性辯證統(tǒng)一思想的體現(xiàn),前者解決了 Bean 個(gè)性化處理的問(wèn)題;而后者解決了容器中某些 Bean 共性化處理的問(wèn)題 。
Spring 容器中可以注冊(cè)多個(gè)后處理器 。 只要它們同時(shí)實(shí)現(xiàn)了 org.springframework.core.Ordered 接口,容器將按特定的順序依次調(diào)用這些后處理器 。 在上圖中帶 “錨” 的步驟,都可以調(diào)用多個(gè)后處理器進(jìn)行一系列的加工處理操作 。
InstantiationAwareBeanPostProcessor 是 BeanPostProcessor 接口的子接口,它的適配器類(lèi)是 InstantiationAwareBeanPostProcessorAdapter ,我們可以方便地?cái)U(kuò)展這個(gè)適配器類(lèi)來(lái)自定義自己感興趣的方法。
1.2 體驗(yàn)生命周期
我們創(chuàng)建一個(gè)類(lèi),讓它實(shí)現(xiàn)所有 Bean 級(jí)的生命周期接口,此外,還通過(guò) <bean> 的 init-method 和 destroy-method 屬性定義了 Bean 初始化和 Bean 銷(xiāo)毀的方法。
public class People implements BeanFactoryAware,BeanNameAware,InitializingBean,DisposableBean{
/**
* 姓名
*/
private String name;
/**
* 年齡
*/
private int age;
/**
* 默認(rèn)構(gòu)造函數(shù)
*/
public People() {
}
/**
* 帶參數(shù)的構(gòu)造函數(shù)
*
* @param name
* @param age
*/
public People(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "People{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("setBeanFactory");
}
@Override
public void setBeanName(String name) {
System.out.println("setBeanName");
}
@Override
public void destroy() throws Exception {
System.out.println("destroy");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("afterPropertiesSet");
}
public void customInit(){
System.out.println("自定義 customInit");
}
public void customDestroy(){
System.out.println("自定義 customDestroy");
}
}
XML 配置:
<bean id="people" class="net.deniro.springBoot.spring4.IoC.People"
init-method="customInit"
destroy-method="customDestroy"
/>
通過(guò)繼承 InstantiationAwareBeanPostProcessorAdapter,可以自定義后處理器:
public class CustomInstantiationAwareBeanPostProcessor extends
InstantiationAwareBeanPostProcessorAdapter {
public static final String PEOPLE_BEAN = "people";
/**
* 在實(shí)例化 Bean 之前調(diào)用
*
* @param beanClass
* @param beanName
* @return
* @throws BeansException
*/
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if (PEOPLE_BEAN.equals(beanName)) {
System.out.println("postProcessBeforeInstantiation");
}
return null;
}
/**
* 在實(shí)例化 Bean 之后調(diào)用
*
* @param bean
* @param beanName
* @return
* @throws BeansException
*/
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if (PEOPLE_BEAN.equals(beanName)) {
System.out.println("postProcessAfterInstantiation");
}
return true;
}
/**
* 設(shè)置某個(gè)屬性
*
* @param pvs
* @param pds
* @param bean
* @param beanName
* @return
* @throws BeansException
*/
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
if (PEOPLE_BEAN.equals(beanName)) {
System.out.println("postProcessPropertyValues");
}
return pvs;
}
}
還可以通過(guò)實(shí)現(xiàn) CustomBeanPostProcessor,來(lái)自定義后處理器,我們可以針對(duì)那些感興趣的 Bean 進(jìn)行加工處理:
public class CustomBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals(PEOPLE_BEAN)) {
People people = (People) bean;
if (people.getName() == null) {
people.setName("deniro");
System.out.println("postProcessBeforeInitialization:"+people);
}
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals(PEOPLE_BEAN)) {
People people = (People) bean;
if (people.getAge() == 0) {
people.setAge(25);
System.out.println("postProcessAfterInitialization:"+people);
}
}
return bean;
}
}
測(cè)試代碼:
/**
* 加載配置文件并啟動(dòng)
*/
Resource resource = new ClassPathResource("beans2.xml");
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(
factory);
reader.loadBeanDefinitions(resource);
//注冊(cè)后處理器
factory.addBeanPostProcessor(new CustomBeanPostProcessor());
factory.addBeanPostProcessor(new CustomInstantiationAwareBeanPostProcessor());
//從容器中獲取 People,實(shí)例化該 Bean,這將引發(fā) Bean 生命周期方法的調(diào)用
People people1 = (People) factory.getBean("people");
System.out.println("people1:" + people1);
people1.setName("lily");
System.out.println("new people1:" + people1);
//第二次從緩存池中獲取 Bean
People people2 = (People) factory.getBean("people");
System.out.println("people1==people2:" + (people1 == people2));
//關(guān)閉容器
factory.destroySingletons();
我們首先裝載了配置文件并啟動(dòng)容器 。 然后向容器中注冊(cè)了 CustomBeanPostProcessor 處理器。 如果有多個(gè)后處理器,可按照相似的方式調(diào)用 addBeanPostProcessor() 方法進(jìn)行注冊(cè),需要強(qiáng)調(diào)的是,后處理器的實(shí)際調(diào)用順序和注冊(cè)順序是無(wú)關(guān)的,在具有多個(gè)后處理器的情況下,必須通過(guò)實(shí)現(xiàn)的 org.springframework.core.Ordered 接口以確定調(diào)用順序 。
1.3 討論
可以通過(guò) <bean> 的 init-method 和 destroy-method 屬性的配置方式為 Bean 指定初始化和銷(xiāo)毀的方法,這樣可以實(shí)現(xiàn)業(yè)務(wù)類(lèi)完全 POJO 化,這些類(lèi)只實(shí)現(xiàn)自己的業(yè)務(wù)接口,不需要和某個(gè)特定框架(包括 Spring 框架)的接口關(guān)聯(lián),從而達(dá)到了與框架解耦的目的。
Spring 中還添加了一個(gè) InitDestroyAnnotationBeanPostProcessor ,該 Bean 后處理器將對(duì)標(biāo)注了 @PostConstruct、@PreDestroy 注解的 Bean 進(jìn)行處理,在 Bean 初始化后及銷(xiāo)毀前執(zhí)行相應(yīng)的邏輯 。 如果在 ApplicationContext 中,則默認(rèn)裝配了該處理器。
BeanFactoryAware 接口可以讓 Bean 感知容器(即 BeanFactory 實(shí)例),而 BeanNameAware 接口可以讓 Bean 獲得配置文件中對(duì)應(yīng)的配置名稱(chēng) 。 如果希望 Bean 獲取容器中的其他 Bean ,則可以通過(guò)屬性注入的方式引用這些 Bean ,如果 Bean 希望在運(yùn)行期獲知在配置文件中的 Bean 名稱(chēng),也可以簡(jiǎn)單地將名稱(chēng)作為屬性注入 。
所以除非想要編寫(xiě)一個(gè)基于 Spring 之上的擴(kuò)展插件或子項(xiàng)目,否則用戶(hù)完全可以?huà)侀_(kāi)Bean 生命周期的接口類(lèi) 。
而 BeanPostProcessor 接口要求 Bean 去繼承它,所以可以完全像一個(gè)插件那樣,把它注冊(cè)到 Spring 容器中,從而為容器提供額外功能 。比如 Spring 容器就利用了 BeanPostProcessor 對(duì) Bean 進(jìn)行加工處理,比如 Spring 的 AOP 功能。
2 ApplicationContext 中 Bean 的生命周期
Bean 在應(yīng)用上下文中的生命周期和在 BeanFactory 中的生命周期類(lèi)似,不同是,如果 Bean 實(shí)現(xiàn)了 org.springframework.context.ApplicationContextAware 接口,則會(huì)增加一個(gè)調(diào)用該接口方法 setApplicationContext() 的步驟。
如果配置文件中定義了多個(gè)工廠后處理器,需要讓它們實(shí)現(xiàn) org.springframework.core.Ordered 接口,這樣才能讓 Spring 以確定的順序調(diào)用它們 。 工廠后處理器是容器級(jí)的,僅在應(yīng)用上下文初始化時(shí)調(diào)用一次,用于完成一些配置文件的加工處理工作 。
ApplicationContext 和 BeanFactory 另一個(gè)不同之處是:前者會(huì)利用 Java 的反射機(jī)制自動(dòng)識(shí)別出配置文件中定義的 BeanPostProcessor、InstantiationAwareBeanPostProcessor 和 BeanFactoryPostProcessor,并自動(dòng)將它們注冊(cè)到應(yīng)用上下文中;而后者需要在代碼中通過(guò)手工調(diào)用 addBeanPostProcessor() 方法進(jìn)行注冊(cè) 。 這也是為什么在應(yīng)用開(kāi)發(fā)時(shí),我們普遍使用的是 ApplicationContext 而很少使用 BeanFactory 的原因之一 。
在 ApplicationContext 中,我們只需要在配置文件中通過(guò) <bean> 定義工廠后處理器和 Bean 后處理器,它們就會(huì)按照預(yù)期的方式運(yùn)行 。

現(xiàn)在請(qǐng)看一個(gè)使用工廠后處理器的實(shí)例,我們?cè)诖烁淖兞? people 實(shí)例的 name:
public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition definition=beanFactory.getBeanDefinition("people");
definition.getPropertyValues().addPropertyValue("name","jack");
System.out.println("CustomBeanFactoryPostProcessor.postProcessBeanFactory()");
}
}
ApplicationContext 在啟動(dòng)時(shí),將首先為配置文件中每個(gè) <bean> 生成一個(gè) BeanDefinition 對(duì)象, BeanDefinition 是 <bean> 在 Spring 容器中的內(nèi)部表示 。
配置文件:
<bean id="people" class="net.deniro.spring4.IoC.People"
init-method="customInit"
destroy-method="customDestroy"
/>
<!-- 工廠的后處理器-->
<bean id="customBeanFactoryPostProcessor"
class="net.deniro.spring4.bean.CustomBeanFactoryPostProcessor"/>
<!-- 注冊(cè) Bean 的后處理器-->
<bean id="customBeanPostProcessor"
class="net.deniro.spring4.bean.CustomBeanPostProcessor"/>
定義的 BeanPostProcessor 和 BeanFactoryPostProcessor 會(huì)自動(dòng)被 ApplicationContext 識(shí)別并注冊(cè)到容器中 。 啟動(dòng)容器(比如 tomcat)就可以看到結(jié)果啦O(∩_∩)O哈哈~
注意:需要在 web.xml 中設(shè)置 spring 配置文件:
...
<!-- 加載 Spring 配置文件-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:beans2.xml</param-value>
</context-param>
...