首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Spring Bean 生命週期完整解析:初始化/銷毀回調、關閉鉤子與預設方法配置

     編輯:Java 綜合教學

一、生命週期核心流程圖

實例化 → 屬性注入 → 【初始化回調】 → Bean 就緒可用 → 容器關閉 → 【銷毀回調】 → 銷毀完成

Spring 容器管理 Bean 從誕生到消亡的全過程,開發者可透過介面、註解或 XML 介入初始化與銷毀兩個關鍵節點。

二、初始化回調三種方式

方式實作優缺點
1. 實作 InitializingBeanvoid afterPropertiesSet() throws Exception強耦合 Spring API,不推薦新專案
2. XML init-method<bean id="x" class="X" init-method="init"/>零侵入,方法名自訂,推薦
3. 註解 @PostConstruct (JSR-250)方法上標註 @PostConstruct標準化、可讀性佳,需 javax.annotation 相依 (Java 9+ 需額外引入)

XML 範例

<bean id="helloWorld" class="com.example.HelloWorld" init-method="init" destroy-method="destroy">
    <property name="message" value="Hello World!"/>
</bean>
public class HelloWorld {
    private String message;
    public void setMessage(String m) { this.message = m; }
    public void getMessage() { System.out.println("Msg: " + message); }
    public void init() { System.out.println("Bean 初始化中..."); }
    public void destroy() { System.out.println("Bean 即將銷毀..."); }
}

三、銷毀回調三種方式

方式實作適用範圍
1. 實作 DisposableBeanvoid destroy() throws Exception同 InitializingBean,不推薦
2. XML destroy-method<bean ... destroy-method="cleanup"/>Singleton Bean,容器關閉時呼叫
3. 註解 @PreDestroy (JSR-250)方法上標註 @PreDestroy標準化,Singleton/Prototype (請求結束) 均適用

重要限制

  • 僅 Singleton Bean 保證執行 destroy-method。Prototype Bean 建立後交由呼叫端管理,容器不追蹤其銷毀。
  • 非 Web 環境 (Main 程式、批次作業) 必須註冊關閉鉤子:
ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
// ... 使用 Bean
ctx.registerShutdownHook(); // JVM 關閉時優雅釋放資源

Web 環境下 ContextLoaderListener / DispatcherServlet 已自動註冊。

四、預設初始化/銷毀方法 (Default Methods)

當大量 Bean 共用相同方法名 (如 init()/destroy()) 時,可在 <beans> 根元素統一宣告:

<beans xmlns="https://www.springframework.org/schema/beans"
       default-init-method="init"
       default-destroy-method="destroy">
    <bean id="beanA" class="com.example.BeanA"/> <!-- 自動綁定 init/destroy -->
    <bean id="beanB" class="com.example.BeanB"/>
</beans>
  • 個別 Bean 仍可用 init-method/destroy-method 覆蓋。
  • 若 Bean 無對應方法,啟動時會拋 BeanCreationException,需確保類別確實定義。

五、完整可執行範例 (Main 程式)

public class MainApp {
    public static void main(String[] args) {
        AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
        HelloWorld bean = ctx.getBean("helloWorld", HelloWorld.class);
        bean.getMessage();
        ctx.registerShutdownHook(); // 關鍵:確保 destroy 被呼叫
    }
}

輸出:

Bean 初始化中...
Msg: Hello World!
Bean 即將銷毀...

六、進階:BeanPostProcessor 介入點

若需在初始化前/後對所有 Bean 進行通用處理 (如 AOP 代理建立、欄位解密、驗證),實作 BeanPostProcessor:

public class MyProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        System.out.println("初始化前: " + beanName);
        return bean; // 可返回代理物件
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        System.out.println("初始化後: " + beanName);
        return bean;
    }
}

在 XML 註冊為 Bean 即自動生效 (無需指定目標 Bean)。

七、最佳實踐總結

  1. 優先使用 @PostConstruct / @PreDestroy:標準、無侵入、IDE 支援佳。
  2. 避免實作 Spring 私有介面:InitializingBean/DisposableBean 造成程式碼耦合框架。
  3. 非 Web 環境務必 registerShutdownHook():否則銷毀回調不會執行,資源洩漏 (連線池、執行緒池、檔案鎖)。
  4. 大量同名回調用 default-init-method:減少 XML 重複,統一維護。
  5. 初始化邏輯保持輕量:耗時操作 (資料庫遷移、大量資料載入) 改用 ApplicationRunner/CommandLineRunner 或 @Async 延後執行。

八、相關學習路徑

  • Spring IoC 容器原理
  • Bean 定義與作用域 (Singleton/Prototype/Request/Session)
  • 依賴注入 (建構子/Setter/Field/@Autowired)
  • BeanPostProcessor 與 AOP 代理建立時機
  • Spring 事件機制 (ApplicationEvent/@EventListener)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved