29

Springを使用して作業中のプロジェクトの1つに循環参照がありますが、これを修正できず、起動時に次のエラーで失敗します。

'org.springframework.security.authenticationManager': Requested bean is currently in creation: Is there an unresolvable circular reference?

サンプルプロジェクトで同じ問題をより小さなレベルで再現しようとしました(作業プロジェクトの詳細はすべて含まれていません)。しかし、私は春がエラーで失敗するというもっともらしいシナリオを思い付くことができませんでした。これが私が持っているものです:

public class ClassA {
    @Autowired
    ClassB classB;
}

public class ClassB {
    @Autowired
    ClassC classC;
}

@Component
public class ClassC {
    @Autowired
    ClassA classA;
}

@Configuration
public class Config {
    @Bean
    public ClassA classA() {
        return new ClassA();
    }

    @Bean
    public ClassB classB() {
        return new ClassB();
    }
}

私のプロジェクトにも同様のシナリオがありますが、失敗します。サンプルプロジェクトでも春に文句を言うことを期待していました。しかし、それはうまくいきます!誰かが循環参照エラーでばねを壊す方法の簡単な例を教えてもらえますか?

編集: javax.inject.Providerを使用して問題を修正しました。2つのプロジェクトのその他の唯一の違いは、使用されたアノテーションが@Autowiredと@Componentの代わりにjavax.inject.Injectとjavax.annotation.ManagedBeanであったことです。

4

3 に答える 3

28

これは古いスレッドなので、この問題をほとんど忘れていたと思いますが、その謎についてお知らせしたいと思います。私は同じ問題に遭遇しましたが、魔法のように消えなかったので、問題を解決する必要がありました. あなたの疑問を一つ一つ解決していきます。

1. 循環参照の例外を再現できなかったのはなぜですか?

Springがそれを処理するからですBean を作成し、必要に応じて注入します

2. では、なぜあなたのプロジェクトは例外を生成するのでしょうか?

  • @sperumal が言ったように、コンストラクター注入を使用すると、Spring は循環例外を生成する可能性があります
  • ログによると、プロジェクトでSpring Securityを使用しています
  • Spring Security 構成では、コンストラクター注入を使用します
  • 注入するあなたの豆authenticationManagerは循環参照を持っていました

3. では、なぜ例外が不可解になくなったのでしょうか?

Bean の作成順序によって、例外が発生する場合と発生しない場合があります。いくつかのファイルを作成したと思いますが*context.xml、web.xml で以下のような構成でそれらをロードします

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:*-context.xml</param-value>
</context-param>

xml ファイルはXmlWebApplicationContextクラスごとにロードされ、ファイルのロード順序は保証されません。ファイルシステムからファイルをロードするだけです。問題はここにあります。クラスが最初にアプリケーション コンテキスト ファイルをロードしても問題はありません。これは、Bean が Spring Security の構築注入に使用されるときに既に作成されているためです。ただし、Spring Security コンテキスト ファイルを最初にロードすると、Spring が作成される前にコンストラクター インジェクションで Bean を使用しようとするため、循環参照の問題が発生します。

4. 問題を解決する方法は?

xml ファイルの読み込み順序を強制します。私の場合、アプリケーション コンテキスト ファイルの最後に、.xml を使用してセキュリティ コンテキスト xml ファイルをロードしました<import resource="">。同じコードでも環境によって読み込み順が変わることがありますので、問題がないように設定することをお勧めします。

于 2014-11-30T06:33:22.287 に答える
28

@Lazyを使用して、Bean が遅延して作成され、自動配線の熱心なサイクルを壊していることを示すことができます。

アイデアは、サイクル上の一部の Bean をプロキシとしてインスタンス化でき、本当に必要な瞬間に初期化されるというものです。つまり、プロキシである Bean を除くすべての Bean が初期化されます。初めて使用すると構成がトリガーされ、他の Bean は既に構成されているため、問題はありません。

Spring-Jira の 1 つの問題から:

@Configuration と組み合わせて使用​​できる @Lazy アノテーションは、その構成クラス内のすべての Bean を遅延初期化する必要があることを示します。もちろん、@Lazy を個々の @Bean メソッドと組み合わせて使用​​して、1 つずつ遅延初期化を示すこともできます。 https://jira.springsource.org/browse/SJC-263

つまり、Bean に as アノテーションを付ける@Lazyだけで十分です。または、次のように構成クラスに注釈を付けるだけの場合@Lazy:

@Configuration
@Lazy
public class Config {
    @Bean
    public ClassA classA() {
        return new ClassA();
    }

    @Bean
    public ClassB classB() {
        return new ClassB();
    }
}

Bean のインターフェースを実装すると、これは非常にうまく機能します。

于 2012-07-05T16:48:04.120 に答える
9

Spring のドキュメントによると、Circular 依存関係の問題を取得するか、コンストラクター インジェクションBeanCurrentlyInCreationExceptionを使用することが可能です。

この問題を解決するには、コンストラクター インジェクションの代わりにセッターを使用します。

http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/beans.htmlを参照してください。

于 2012-07-05T16:54:06.027 に答える