1. 概述
Spring 默認管理 Bean 的生命週期並安排其初始化順序。
但是,我們可以根據需要進行自定義。 我們可以選擇使用 SmartLifeCycle 接口或使用 @DependsOn 註解來管理初始化順序。
本教程將探討 @DependsOn 註解及其在 Bean 缺失、循環依賴或僅僅需要一個 Bean 在另一個 Bean 之前初始化時的行為。
2. <em @DependsOn>
我們應該使用此註解來指定 Bean 依賴關係。 Spring 保證在嘗試當前 Bean 初始化之前,已定義的 Bean 已經被初始化。
例如,我們有一個 FileProcessor,它依賴於 FileReader 和 FileWriter。在這種情況下,FileReader 和 FileWriter 應該在 FileProcessor 初始化之前被初始化。
3. 配置
配置文件是一個純 Java 類,帶有 @Configuration 註解:
@Configuration
@ComponentScan("com.baeldung.dependson")
public class Config {
@Bean
@DependsOn({"fileReader","fileWriter"})
public FileProcessor fileProcessor(){
return new FileProcessor();
}
@Bean("fileReader")
public FileReader fileReader() {
return new FileReader();
}
@Bean("fileWriter")
public FileWriter fileWriter() {
return new FileWriter();
}
}FileProcessor 通過使用 @DependsOn 聲明其依賴關係。 此外,我們還可以使用 @DependsOn: 註解一個 Component。
@Component
@DependsOn({"filereader", "fileWriter"})
public class FileProcessor {}4. 使用方法
讓我們創建一個名為 <em File</em> 的類。每個 Bean 都更新 <em File</em> 中的文本。<em FileReader</em> 在讀取時進行更新,<em FileWriter</em> 在寫入時進行更新,<em FileProcessor</em> 在處理文本時進行更新:
@Test
public void WhenFileProcessorIsCreated_FileTextContains_Processed() {
FileProcessor processor = context.getBean(FileProcessor.class);
assertTrue(processor.process().endsWith("processed"));
}4.1. 缺失依賴
如果缺少依賴,Spring 會拋出 <em>BeanCreationException</em> 異常,其基礎異常是 <em>NoSuchBeanDefinitionException</em>。 更多關於 <em>NoSuchBeanDefinitionException</em> 的信息,請參考這裏。
例如,<em>dummyFileProcessor</em> bean 依賴於 <em>dummyFileWriter</em> bean。 由於 <em>dummyFileWriter</em> 不存在,因此它會拋出 <em>BeanCreationException</em>:
@Test(expected=NoSuchBeanDefinitionException.class)
public void whenDependentBeanNotAvailable_ThrowsNosuchBeanDefinitionException(){
context.getBean("dummyFileProcessor");
}4.2. 循環依賴
此外,在這種情況下,它會拋出 BeanCreationException,並指出這些 Bean 之間存在循環依賴關係:
@Bean("dummyFileProcessorCircular")
@DependsOn({"dummyFileReaderCircular"})
@Lazy
public FileProcessor dummyFileProcessorCircular() {
return new FileProcessor(file);
}循環依賴可能發生在 Bean 對自身產生最終依賴時,從而形成循環:
Bean1 -> Bean4 -> Bean6 -> Bean15. 關鍵要點
請在使用 <em data-language="DependsOn">@DependsOn</em> 註解時注意以下幾點:
- 在使用
<em data-language="DependsOn">@DependsOn</em>註解時,必須使用組件掃描。 - 如果通過 XML 聲明的
<em data-language="DependsOn">@DependsOn</em>註解化的類,則忽略<em data-language="DependsOn">@DependsOn</em>註解的元數據。
6. 結論
@DependsOn 在構建具有複雜依賴要求的系統時尤其有用。
它促進了依賴注入,確保 Spring 會在加載我們的依賴類之前,已處理所有必需 Bean 的初始化。