私は春を使用して仕事で私のプロジェクトの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であったことです。
これは古いスレッドなので、この問題をほとんど忘れていたと思いますが、その謎についてお知らせしたいと思います。私は同じ問題に遭遇し、私のものは魔法のように消えなかったので、問題を解決しなければなりませんでした。あなたの質問を段階的に解決します。
1。循環参照例外を再現できなかったのはなぜですか?
Springが処理します。必要に応じてBeanを作成して注入します 。
2。では、なぜプロジェクトで例外が発生するのですか?
authenticationManager
を注入するBeanには循環参照がありました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が最初にSpring Securityコンテキストファイルをロードすると、作成される前にSpringがコンストラクターインジェクションでBeanを使用しようとするため、循環参照の問題が発生します。
4。問題の解決方法
Xmlファイルの読み込み順序を強制します。私の場合、<import resource="">
を使用して、アプリケーションコンテキストファイルの最後にセキュリティコンテキストxmlファイルをロードしました。ロード順序は、同じコードを使用している場合でも環境に応じて変更できるため、潜在的な問題を削除するように順序を設定することをお勧めします。
@Lazy
を使用して、Beanが遅延的に作成され、自動配線の熱心なサイクルが中断されることを示すことができます。
アイデアは、サイクル上の一部のBeanをプロキシとしてインスタンス化でき、実際に必要になった瞬間に初期化されるというものです。つまり、プロキシであるBeanを除くすべてのBeanが初期化されます。初めて使用すると設定がトリガーされ、他のBeanはすでに設定されているため、問題にはなりません。
Spring-Jiraの1つの問題から:
@Configurationと併用して、その構成クラス内のすべてのBeanを遅延初期化する必要があることを示す@Lazyアノテーション。もちろん、@ Lazyを個々の@Beanメソッドと組み合わせて使用して、レイジー初期化を1つずつ行うこともできます。 https://jira.springsource.org/browse/SJC-26
Beanに@Lazy
として注釈を付けるだけで十分であることを意味します。または、次のように@Lazy
として構成クラスに注釈を付けるだけの場合:
@Configuration
@Lazy
public class Config {
@Bean
public ClassA classA() {
return new ClassA();
}
@Bean
public ClassB classB() {
return new ClassB();
}
}
Beanのインターフェースを実装する場合、これは非常にうまく機能します。
Springのドキュメントによると、constructor injectionを使用して、循環依存の問題またはBeanCurrentlyInCreationException
を取得することができます。
この問題を解決する解決策は、コンストラクター注入の代わりにセッターを使用することです。
リファレンス http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/beans.html 。