一、Spring Bean的生命周期
Spring Bean的生命周期指的是Bean從創建到銷毀的整個過程。理解這個生命周期對于正確使用Spring框架至關重要,它可以幫助我們在適當的時機執行自定義邏輯。
1. 完整的Bean生命周期階段
Spring Bean的生命周期可以分為以下幾個主要階段:
-
實例化(Instantiation):容器通過構造函數或工廠方法創建Bean實例
-
屬性填充(Populate properties):設置Bean的屬性值和依賴
-
BeanNameAware.setBeanName():如果實現了BeanNameAware接口
-
BeanFactoryAware.setBeanFactory():如果實現了BeanFactoryAware接口
-
ApplicationContextAware.setApplicationContext():如果實現了ApplicationContextAware接口
-
BeanPostProcessor.postProcessBeforeInitialization():BeanPostProcessor的前置處理
-
@PostConstruct注解的方法:執行初始化回調
-
InitializingBean.afterPropertiesSet():如果實現了InitializingBean接口
-
自定義init-method:執行配置的初始化方法
-
BeanPostProcessor.postProcessAfterInitialization():BeanPostProcessor的后置處理
-
Bean就緒可用:此時Bean可以被正常使用
-
@PreDestroy注解的方法:容器關閉時執行銷毀回調
-
DisposableBean.destroy():如果實現了DisposableBean接口
-
自定義destroy-method:執行配置的銷毀方法
2. 生命周期示例代碼
public class ExampleBean implements BeanNameAware, InitializingBean, DisposableBean {private String name;public ExampleBean() {System.out.println("1. 實例化Bean");}public void setName(String name) {System.out.println("2. 設置屬性值");this.name = name;}@Overridepublic void setBeanName(String name) {System.out.println("3. BeanNameAware.setBeanName()");}@PostConstructpublic void postConstruct() {System.out.println("5. @PostConstruct方法");}@Overridepublic void afterPropertiesSet() {System.out.println("6. InitializingBean.afterPropertiesSet()");}public void customInit() {System.out.println("7. 自定義init-method");}@PreDestroypublic void preDestroy() {System.out.println("9. @PreDestroy方法");}@Overridepublic void destroy() {System.out.println("10. DisposableBean.destroy()");}public void customDestroy() {System.out.println("11. 自定義destroy-method");}
}// 配置類
@Configuration
public class AppConfig {@Bean(initMethod = "customInit", destroyMethod = "customDestroy")public ExampleBean exampleBean() {ExampleBean bean = new ExampleBean();bean.setName("示例Bean");return bean;}
}
3. 生命周期流程圖
實例化Bean → 設置屬性 → Aware接口回調 → BeanPostProcessor前置處理 →
@PostConstruct → afterPropertiesSet → init-method →
BeanPostProcessor后置處理 → Bean就緒可用 →
@PreDestroy → destroy() → destroy-method
二、Spring Bean的作用域
Spring框架支持多種Bean作用域,允許開發者根據需求控制Bean的創建方式和生命周期。
1. 標準作用域
Spring提供了以下標準作用域:
-
singleton(單例,默認):
-
每個Spring IoC容器中一個Bean定義對應一個實例
-
所有對該Bean的請求都返回同一個實例
-
生命周期與容器相同
-
-
prototype(原型):
-
每次請求都創建一個新的Bean實例
-
適用于有狀態的Bean
-
Spring不管理完整的生命周期,只負責初始化
-
-
request(請求):
-
每個HTTP請求創建一個新的Bean
-
僅適用于Web應用
-
請求結束時銷毀
-
-
session(會話):
-
每個HTTP會話創建一個Bean
-
僅適用于Web應用
-
會話結束時銷毀
-
-
application(應用):
-
每個ServletContext生命周期創建一個Bean
-
類似單例,但范圍是ServletContext而非Spring容器
-
-
websocket(WebSocket):
-
每個WebSocket會話創建一個Bean
-
僅適用于WebSocket應用
-
2. 作用域配置示例
XML配置方式:
<bean id="accountService" class="com.example.AccountService" scope="prototype"/>
Java注解方式:
@Bean
@Scope("prototype")
public AccountService accountService() {return new AccountService();
}
使用@Scope注解:
@Service
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class PrototypeService {// ...
}
3. 作用域選擇建議
-
無狀態服務:使用singleton(默認),性能最佳
-
有狀態組件:使用prototype,避免并發問題
-
Web相關數據:根據需要使用request、session等作用域
-
線程安全考慮:prototype作用域可以避免線程安全問題,但會增加創建開銷
4. 自定義作用域
Spring還允許注冊自定義作用域:
public class ThreadScope implements Scope {// 實現Scope接口方法
}// 注冊自定義作用域
ConfigurableBeanFactory factory = (ConfigurableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
factory.registerScope("thread", new ThreadScope());// 使用自定義作用域
@Bean
@Scope("thread")
public MyBean myBean() {return new MyBean();
}
三、生命周期與作用域的關系
不同作用域的Bean生命周期有所不同:
-
singleton:
-
容器啟動時初始化(默認懶加載除外)
-
容器關閉時銷毀
-
完整的生命周期回調
-
-
prototype:
-
每次請求時初始化
-
容器不跟蹤實例,不會調用銷毀方法
-
只有部分生命周期回調
-
-
request/session:
-
請求/會話開始時初始化
-
請求/會話結束時銷毀
-
完整的生命周期回調
-
四、最佳實踐
-
盡量使用singleton作用域:性能最佳,適用于無狀態服務
-
謹慎使用prototype:僅在必要時使用,注意資源釋放
-
合理使用生命周期回調:資源初始化/釋放放在合適的回調中
-
避免在singleton中注入prototype:會導致prototype失去意義,可以使用方法注入解決
-
Web作用域Bean不要注入singleton:會導致狀態不一致
五、總結
理解Spring Bean的生命周期和作用域對于開發高質量的Spring應用至關重要。通過合理利用生命周期回調和選擇適當的作用域,可以構建出既高效又可靠的應用程序。記住,大多數情況下默認的singleton作用域是最佳選擇,只有在確實需要時才使用其他作用域。