轉發
http://java265.com/JavaFramework/Spring/202107/504.html
我們都知道,在使用new關鍵字實體化的Java Bean,它的生命周期非常簡單,當Java Bean不需要使用時,則Java會自動進行垃圾回收,
所以它的生命周期會非常容易理解,
但Spring中Bean的生命周期,則較為復雜,它由Bean定義->Bean初始化->Bean應用->Bean銷毀
Spring 針對不同Bean的作用域采用不同的管理方式
對采用singleton 作用域Bean,Spring可清楚的知道它的創建及初始化時間及銷毀時間,
但是對于prototype作用域下的Bean,Spring框架則只負責創建,當創建完畢后,則將Bean實體交給客戶端代碼管理,
Spring將不對此型別的Bean進行生命周期管理
Spring Bean生命周期執行流程
Spring 容器在確保一個 Bean 能夠使用之前,會進行很多作業,Spring 容器中 Bean 的生命周期流程如下圖所示

Bean 生命周期流程
- Spring 啟動,查找并加載需要被Spring 管理的 Bean,并實體化 Bean,
- 利用依賴注入完成 Bean 中所有屬性值的配置注入,
- 當Bean 實作了 BeanNameAware 介面,則 Spring 呼叫 Bean 的 setBeanName() 方法傳入當前 Bean 的 id 值,
- 當Bean 實作了 BeanFactoryAware 介面,則 Spring 呼叫 setBeanFactory() 方法傳入當前工廠實體的參考,
- 當Bean 實作了 ApplicationContextAware 介面,則 Spring 呼叫 setApplicationContext() 方法傳入當前 ApplicationContext 實體的參考,
- 當Bean 實作了 BeanPostProcessor 介面,則 Spring 呼叫該介面的預初始化方法 postProcessBeforeInitialzation() 對 Bean 進行加工操作,此處非常重要,Spring 的 AOP 就是利用它實作的,
- 當Bean 實作了 InitializingBean 介面,則 Spring 將呼叫 afterPropertiesSet() 方法,
- 當在組態檔中通過 init-method 屬性指定了初始化方法,則呼叫該初始化方法,
- 當BeanPostProcessor 和 Bean 關聯,則 Spring 將呼叫該介面的初始化方法 postProcessAfterInitialization(),此時,Bean 已經可以被應用系統使用了,
- 當在 <bean> 中指定了該 Bean 的作用域為 singleton,則將該 Bean 放入 Spring IoC 的快取池中,觸發 Spring 對該 Bean 的生命周期管理;如果在 <bean> 中指定了該 Bean 的作用域為 prototype,則將該 Bean 交給呼叫者,呼叫者管理該 Bean 的生命周期,Spring 不再管理該 Bean,
- 當Bean 實作了 DisposableBean 介面,則 Spring 會呼叫 destory() 方法銷毀 Bean;如果在組態檔中通過 destory-method 屬性指定了 Bean 的銷毀方法,則 Spring 將呼叫該方法對 Bean 進行銷毀,
Spring 為 Bean 提供了細致全面的生命周期程序,實作特定的介面或設定 <bean> 的屬性都可以對 Bean 的生命周期程序產生影響,建議不要過多的使用 Bean 實作介面,因為這樣會導致代碼的耦合性過高,
了解 Spring 生命周期的意義就在于,可以利用 Bean 在其存活期間的指定時刻完成一些相關操作,一般情況下,會在 Bean 被初始化后和被銷毀前執行一些相關操作,
Spring 官方提供了 3 種方法實作初始化回呼和銷毀回呼:
- 實作 InitializingBean 和 DisposableBean 介面;
- 在 XML 中配置 init-method 和 destory-method;
- 使用 @PostConstruct 和 @PreDestory 注解,
在一個 Bean 中有多種生命周期回呼方法時,優先級為:注解 > 介面 > XML,
不建議使用介面和注解,這會讓 pojo 類和 Spring 框架緊耦合,
初始化回呼
1. 使用介面
org.springframework.beans.factory.InitializingBean 介面提供了以下方法:
- void afterPropertiesSet() throws Exception;
您可以實作以上介面,在 afterPropertiesSet 方法內指定 Bean 初始化后需要執行的操作,
<bean id="..." class="..." /> public class User implements InitializingBean { @Override public void afterPropertiesSet() throws Exception { System.out.println("呼叫介面:InitializingBean,方法:afterPropertiesSet,無引數"); } }
2. 配置XML
可以通過 init-method 屬性指定 Bean 初始化后執行的方法
<bean id="..." class="..." init-method="init"/> public class User { public void init() { System.out.println("呼叫init-method指定的初始化方法:init" ); } }
3. 使用注解
使用 @PostConstruct 注解標明該方法為 Bean 初始化后的方法,
public class ExampleBean { @PostConstruct public void init() { System.out.println("@PostConstruct注解指定的初始化方法:init" ); } }
銷毀回呼
1. 使用介面
org.springframework.beans.factory.DisposableBean 介面提供了以下方法: void destroy() throws Exception;
您可以實作以上介面,在 destroy 方法內指定 Bean 初始化后需要執行的操作,
<bean id="..." class="..." /> public class User implements DisposableBean
{
@Override
public void destory() throws Exception {
System.out.println("銷毀方法");
}
}
2. 配置XML
可以通過 destroy-method 屬性指定 Bean 銷毀后執行的方法
<bean id="..." class="..." destroy-method="destroy"/> public class User { public void destroy() { System.out.println("呼叫destroy-method指定的銷毀方法:destroy" ); } }
3. 使用注解
使用 @PreDestory 注解標明該方法為 Bean 銷毀前執行的方法,
public class ExampleBean { @PreDestory public void destroy() { System.out.println("@PreDestory注解指定的初始化方法:destroy" ); } }
例
下面使用 Eclipse IDE 演示如何通過配置 XML 的方式實作初始化回呼和銷毀回呼,步驟如下:
- 創建 SpringDemo 專案,并在 src 目錄下創建 com.java265包,
- 添加相應的 jar 包,可以參考《第一個Spring程式》一節,
- 在 com.java265 包下創建 HelloWorld 和 MainApp 類,
- 在 src 目錄下創建 Spring 組態檔 Beans.xml,
- 運行 SpringDemo 專案
HelloWorld 類-----
package com.java265; public class HelloWorld { private String message; public void setMessage(String message) { this.message = message; } public void getMessage() { System.out.println("message : " + message); } public void init() { System.out.println("Bean正在進行初始化"); } public void destroy() { System.out.println("Bean將要被銷毀"); } }
MainApp 類代碼如下,該類中我們使用 AbstractApplicationContext 類的 registerShutdownHook() 方法,來確保正常關機并呼叫相關的 destroy() 方法,
package com.java265; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MainApp { public static void main(String[] args) { AbstractApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml"); HelloWorld obj = (HelloWorld) context.getBean("helloWorld"); obj.getMessage(); context.registerShutdownHook(); } }
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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="helloWorld" class="com.java265.HelloWorld" init-method="init" destroy-method="destroy"> <property name="message" value="https://www.cnblogs.com/java265/p/Hello World!" /> </bean> </beans>
-----運行結果-----
Bean正在進行初始化
message : Hello World!
Bean將要被銷毀
默認的初始化和銷毀方法
如果多個 Bean 需要使用相同的初始化或者銷毀方法,不用為每個 bean 宣告初始化和銷毀方法,可以使用 default-init-method 和 default-destroy-method 屬性,如下:
<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-3.0.xsd" default-init-method="init" default-destroy-method="destroy"> <bean id="..." class="..."> ... </bean> </beans>
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/476943.html
標籤:Java
