1. 概要

Springは、デフォルトで、Beanのライフサイクルを管理し、初期化の順序を調整します。

ただし、ニーズに基づいてカスタマイズすることはできます。 初期化順序を管理するためにSmartLifeCycleインターフェースまたは@DependsOnアノテーションのいずれかを選択できます

このチュートリアルでは、 @DependsOn アノテーションと、Beanが欠落している場合または循環依存関係の場合の動作について説明します。 または、あるBeanを別のBeanの前に初期化する必要がある場合。

2. Maven

まず、springコンテキストの依存関係をpom.xmlファイルにインポートしましょう。 依存関係の最新バージョンについては、常にMavenCentralを参照する必要があります。

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.8.RELEASE</version>
</dependency>

3. @DependsOn

Beanの依存関係を指定するには、このアノテーションを使用する必要があります。 Springは、現在のBeanの初期化を試みる前に、定義されたBeanが初期化されることを保証します。

FileReaderFileWriterに依存するFileProcessorがあるとします。 この場合、FileReaderおよびFileWriterは、FileProcessorの前に初期化する必要があります。

4. 構成

構成ファイルは、@Configurationアノテーションが付いた純粋なJavaクラスです。

@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
@DependsOn({"filereader", "fileWriter"})
public class FileProcessor {}

5. 使用法

1つのクラスFileを作成しましょう。 各Beanは、ファイル内のテキストを更新します。 FileReaderはそれを既読として更新します。 FileWriter は書き込みとして更新し、FileProcessorは処理済みとしてテキストを更新します。

@Test
public void WhenFileProcessorIsCreated_FileTextContains_Processed() {
    FileProcessor processor = context.getBean(FileProcessor.class);
    assertTrue(processor.process().endsWith("processed"));
}

5.1. 依存関係の欠如

依存関係が欠落している場合、Springは BeanCreationException をスローしますが、基本例外はNoSuchBeanDefinitionExceptionです。 NoSuchBeanDefinitionException詳細はこちらをご覧ください。

たとえば、 dummyFileProcessor Beanは、dummyFileWriterBeanに依存しています。 dummyFileWriter が存在しないため、 BeanCreationException:をスローします。

@Test(expected=NoSuchBeanDefinitionException.class)
public void whenDependentBeanNotAvailable_ThrowsNosuchBeanDefinitionException(){
    context.getBean("dummyFileProcessor");
}

5.2. 循環依存

また、この場合、 BeanCreationException をスローし、Beanに循環依存関係があることを強調表示します。

@Bean("dummyFileProcessorCircular")
@DependsOn({"dummyFileReaderCircular"})
@Lazy
public FileProcessor dummyFileProcessorCircular() {
    return new FileProcessor(file);
}

Beanが最終的にそれ自体に依存している場合、循環依存が発生する可能性があり、次のようになります。

Bean1 -> Bean4 -> Bean6 -> Bean1

6. キーポイント

最後に、@DependsOnアノテーションを使用する際に注意すべき点がいくつかあります。

  • @DependsOn、を使用している間は、コンポーネントスキャンを使用する必要があります
  • DependsOn アノテーション付きクラスがXMLを介して宣言されている場合、DependsOnアノテーションメタデータは無視されます

7. 結論

@DependsOn は、複雑な依存関係要件を持つシステムを構築する場合に特に役立ちます。

これにより、依存性注入が容易になり、Springが依存クラスをロードする前に必要なBeanの初期化をすべて処理できるようになります。

いつものように、コードはGitHubにあります。