1. 程式人生 > >【Spring註解驅動開發】使用InitializingBean和DisposableBean來管理bean的生命週期,你真的瞭解嗎?

【Spring註解驅動開發】使用InitializingBean和DisposableBean來管理bean的生命週期,你真的瞭解嗎?

## 寫在前面 > 在《[【Spring註解驅動開發】如何使用@Bean註解指定初始化和銷燬的方法?看這一篇就夠了!!](https://mp.weixin.qq.com/s?__biz=Mzg3MzE1NTIzNA==&mid=2247484985&idx=1&sn=bf7ec702113f433f6677d0e9f4f5ae7d&chksm=cee519f4f99290e2c509926a61a7f9604d8a358cd364a78d6de7929f45b3b2a84f57b93f8f87&token=604767871&lang=zh_CN#rd)》一文中,我們講述瞭如何使用@Bean註解來指定bean初始化和銷燬的方法。具體的用法就是在@Bean註解中使用init-method屬性和destroy-method屬性來指定初始化方法和銷燬方法。除此之外,Spring中是否還提供了其他的方式來對bean例項進行初始化和銷燬呢? > > 專案工程原始碼已經提交到GitHub:[https://github.com/sunshinelyz/spring-annotation](https://github.com/sunshinelyz/spring-annotation) ## InitializingBean介面 ### 1.InitializingBean介面概述 Spring中提供了一個InitializingBean介面,InitializingBean介面為bean提供了屬性初始化後的處理方法,它只包括afterPropertiesSet方法,凡是繼承該介面的類,在bean的屬性初始化後都會執行該方法。InitializingBean介面的原始碼如下所示。 ```java package org.springframework.beans.factory; public interface InitializingBean { void afterPropertiesSet() throws Exception; } ``` 根據InitializingBean介面中提供的afterPropertiesSet()方法的名字可以推斷出:afterPropertiesSet()方法是在屬性賦好值之後呼叫的。那到底是不是這樣呢?我們來分析下afterPropertiesSet()方法的呼叫時機。 ### 2.何時呼叫InitializingBean介面? 我們定位到Spring中的org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory類下的invokeInitMethods()方法中,來檢視Spring載入bean的方法。 **題外話:不要問我為什麼會是這個invokeInitMethods()方法,如果你和我一樣對Spring的原始碼非常熟悉的話,你也會知道是這個invokeInitMethods()方法,哈哈哈哈!所以,小夥伴們不要只顧著使用Spring,還是要多看看Spring的原始碼啊!Spring框架中使用了大量優秀的設計模型,其程式碼的編寫規範和嚴謹程度也是業界開源框架中數一數二的,非常值得閱讀。** 我們來到AbstractAutowireCapableBeanFactory類下的invokeInitMethods()方法,如下所示。 ```java protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd) throws Throwable { //判斷該bean是否實現了實現了InitializingBean介面,如果實現了InitializingBean介面,則呼叫bean的afterPropertiesSet方法 boolean isInitializingBean = (bean instanceof InitializingBean); if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { if (logger.isTraceEnabled()) { logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); } if (System.getSecurityManager() != null) { try { AccessController.doPrivileged((PrivilegedExcepti