相互に自動配線するSpringBeanのグラフがあります。非常に簡略化された図:
<context:annotation-config/>
<bean class="Foo"/>
<bean class="Bar"/>
<bean class="Baz"/>
...
public class Foo {
@Autowired Bar bar;
@Autowired Baz baz;
}
public class Bar {
@Autowired Foo foo;
}
public class Baz {
@Autowired Foo foo;
}
これらのBeanはすべて、シングルトンであることを意味するスコープが指定されていません(明示的なシングルトンにしても、何も変更されません。私は試しました)。
問題は、単一のアプリケーションコンテキストのインスタンス化後、のインスタンスBar
とが異なるインスタンスをBaz
含むことです。これはどのように起こりますか?Foo
public no argsコンストラクターを作成しようとしましたがFoo
、デバッグFoo
で複数回作成されていることが確認されました。これらすべての作成のスタックトレースはここにあります。
また、Springのデバッグログを有効にしようとしましたが、他のすべての行の中で、次のようになりました。
DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'Foo'
DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'Foo'
DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'Foo'
Beanが相互参照していることは理解していますが、Springフレームワークがシングルトンスコープを尊重し、シングルトンBeanを一度初期化してから、必要な人に自動配線することを期待しています。
private
アクセサーで古い学校のコンストラクターを使用する場合、これは問題なく機能するという興味深い事実public static Foo getInstance
-コンテキストのセットアップ中に例外はスローされません。
FWIW、私はo.s.c.s.ClassPathXmlApplicationContext(String ...configLocations)
コンストラクターでSpringバージョン3.0.5(3.1.2でも試してみました、同じ結果)を使用しています。
静的初期化子を使用するようにコードを簡単に変換できますが、Springがこのように動作する理由を理解したいと思います。これはバグですか?
編集:いくつかの追加の調査はそれを示しました
- アプリケーションコンテキストが初期化された後、後続のすべてのリクエストは
context.getBean(Foo.class)
常に同じインスタンスを返しますFoo
。 @Autowired
セッター(このBeanの約20回の使用)で置き換えても、このオブジェクトは複数構築されますが、すべての依存関係に同じ参照が挿入されます。
上記の私には、これは@Autowired
実装に関連するSpringのバグであることが示唆されています。何か役に立つものを手に入れることができたら、Springコミュニティフォーラムに投稿し、ここに投稿します。