コンストラクター注入とセッター注入はそれぞれ循環依存関係を処理します

循環依存関係は、2 つ以上の Bean が相互に依存する場合に発生します。Spring では、コンストラクター インジェクションとセッター インジェクションは循環依存関係を異なる方法で処理します。以下では、循環依存関係を処理する場合のこれら 2 つの注入方法の戦略について説明します。

1. コンストラクターの注入

コンストラクター インジェクションでは、Bean の作成時に Spring が依存関係パラメーターを指定してコンストラクターを呼び出す必要があるため、循環依存関係によって問題が発生する可能性があります。2 つの Bean が相互に依存している場合、各 Bean の作成にはパラメーターとしてもう一方の Bean が必要となるため、Spring はそれらを同時に作成できません。この場合、Spring は循環依存関係を解決できず、BeanCurrentlyInCreationException をスローします。

例えば:

public class FooService {
    
    
    private final BarService barService;

    public FooService(BarService barService) {
    
    
        this.barService = barService;
    }
}

public class BarService {
    
    
    private final FooService fooService;

    public BarService(FooService fooService) {
    
    
        this.fooService = fooService;
    }
}

上の例では、FooService は BarService に依存し、BarService は FooService に依存します。どちらもコンストラクターを通じて依存関係を注入するため、これら 2 つの Bean を作成するときに Spring は無限ループに陥り、最終的に例外をスローします。

2. セッターの注入

循環依存関係は、セッター注入では異なる方法で処理されます。この場合、Spring は循環依存関係の問題を解決できます。Setter インジェクションを使用する場合、Spring は最初に Bean のインスタンスを作成し、次に setter メソッドを通じて依存関係を注入します。これは、Bean が作成された時点では、その依存関係がまだ注入されていない可能性があることを意味します。Spring は、Bean の依存関係がすべて注入されるまで、Bean を作成済みとしてマークしません。

例えば:

public class FooService {
    
    
    private BarService barService;

    public void setBarService(BarService barService) {
    
    
        this.barService = barService;
    }
}

public class BarService {
    
    
    private FooService fooService;

    public void setFooService(FooService fooService) {
    
    
        this.fooService = fooService;
    }
}

上の例では、FooService は BarService に依存し、BarService は FooService に依存します。ただし、どちらも Setter を通じて依存関係を注入するため、Spring は最初にこれら 2 つの Bean のインスタンスを作成してから、それらの依存関係を注入できます。このようにして、Spring は循環依存関係の問題を解決できます。

すべての依存関係が注入されるまで Bean の状態が完了しない可能性があるため、循環依存関係を解決するとオブジェクトの状態が不安定になる可能性があることに注意してください。これにより、実行時エラーや予期しない動作が発生する可能性があります。したがって、Setter インジェクションは循環依存の問題を解決できますが、それでも循環依存を避けるように努める必要があります。

3. まとめ

コンストラクター注入とセッター注入では、循環依存関係の処理方法が異なります。コンストラクターインジェクションでは、循環依存関係の問題を解決できません。Bean を作成するときに、Spring は依存パラメーターを指定してコンストラクターを呼び出す必要があり、その結果、無限ループと例外が発生するためです。Spring は最初に Bean のインスタンスを作成し、次に setter メソッドを通じて依存関係を注入するため、Setter 注入によって循環依存関係を解決できます。

それでも、循環依存関係はオブジェクトの状態が不安定になったり、実行時エラーが発生したりする可能性があるため、回避する必要があります。設計時に、循環依存関係を回避するために次の戦略を採用できます。

  1. システム アーキテクチャとクラス設計を再検討し、相互依存するクラスをより小さな独立したコンポーネントに分割して、低結合で凝集性の高い設計を実現します。
  2. 中間モードやオブザーバー モードなどの設計パターンを使用して、クラス間の直接の依存関係を減らします。
  3. 依存関係ルックアップ (依存関係ルックアップ) や、遅延読み込みやプロキシなどの依存関係注入コンテナーによって提供されるその他の高度な機能を使用して、特定のシナリオにおける循環依存関係の問題を解決します。

実際の開発では、システムの保守性と安定性を確保するために、循環依存関係を避けるように努める必要があります。循環依存関係の問題が発生した場合は、プロジェクトの要件とクラスの特性に応じて適切な処理戦略を選択できます。

おすすめ

転載: blog.csdn.net/kaka_buka/article/details/129988077