web-dev-qa-db-ja.com

春の自動配線順序と@PostConstruct

Springでの自動配線の順序と@PostConstructロジックについて質問があります。たとえば、次のデモコードには、メインのSpring Bootクラスがあります。

@SpringBootApplication
public class Demo1Application {

    @Autowired
    BeanB beanb;

    public static void main(String[] args) {
        SpringApplication.run(Demo1Application.class, args);
    }
}

および2 @Service定義:

@Service
public class BeanB {

    @Autowired
    private BeanA beana ;

    @PostConstruct
    public void init(){
        System.out.println("beanb is called");
    }

    public void printMe(){
        System.out.println("print me is called in Bean B");
    }
}

@Service
public class BeanA {

    @Autowired
    private BeanB b;

    @PostConstruct
    public void init(){
        System.out.println("bean a is called");
        b.printMe();
    }
}

そして、私は次の出力を持っています:

bean aと呼ばれる

プリントBは、Bean Bで呼び出されます

beanbが呼び出されます


私の質問は、上記のシナリオのように、ステップごとに自動配線が行われる方法ですか?
そして、最初に@PostConstructを呼び出さずにbeanbprintMe()メソッドを呼び出す方法は?

25
cacert

以下は可能なシーケンスでなければなりません

  1. beanbは自動配線を開始します
  2. Beanbのクラス初期化中に、ビーナは自動配線を開始します
  3. Beanaが作成されると、_@PostConstruct_つまりbeanaのinit()が呼び出されます
  4. init()内で、System.out.println("bean a is called");が呼び出されます
  5. 次に、b.printMe();が呼び出され、System.out.println("print me is called in Bean B");が実行されます
  6. beanaが_@PostConstruct_を完了すると、つまりbeanbinit()が呼び出されます
  7. 次に、System.out.println("beanb is called");が呼び出されます

理想的には、Eclipseのデバッガーでも同じことがよく観察できます。

Springリファレンスマニュアル では、循環依存関係の解決方法について説明しています。 Beanは最初にインスタンス化され、次に相互に注入されます。

14
Mudassar

あなたの質問に示したとおり、あなたの答えは正しいです。

表記法@Autowiredの概念を取得します。すべての@Autowiredオブジェクトは、クラスの読み込みが完了した直後に初期化され、メモリに読み込まれます。

これがSpringBootApplicationです

@SpringBootApplication
public class Demo1Application {
    @Autowired
    BeanB beanb;   // You are trying to autowire a Bean class Named BeanB.

上の上記のコンソールアプリケーションで、タイプBeanBのオブジェクトを自動配線して挿入しようとします。

これがBeanBの定義です

@Service
public class BeanB {

    @Autowired
    private BeanA beana ;

BeanBクラスでは、コンソールプロジェクトでも定義されているBeanAクラスのオブジェクトを挿入しようとしています。

したがって、Demo1ApplicationクラスのオブジェクトBeanBを注入するには、BeanAクラスのオブジェクトを注入する必要があります。これで、BeanAクラスオブジェクトが最初に作成されます。

クラスの定義が表示されたらBeanA

 @Service
public class BeanA {

    @Autowired
    private BeanB b;

    @PostConstruct   // after Creating bean init() will be execute.
    public void init(){
        System.out.println("bean a is called");
        b.printMe();
    }
}

そのため、オブジェクトを挿入した後、BeanAメソッド@PostContructアノテーションを使用してバインドを実行します。

したがって、実行フローは...

System.out.println("bean a is called");
System.out.println("print me is called in Bean B");
System.out.println("beanb is called");
5
Vikrant Kashyap