2013-03-03 18 views
8

循環依存性を避けるためにこれを読んでいます。コンストラクタの代わりにセッターに@Autowiredを使用できます。セッターを使用したSpringの循環依存性

もしそうなら、これはなぜ失敗するのですか?

@Component 
private static class A { 
    @Autowired 
    public A(B b) { 
    } 
} 

@Component 
private static class B { 
    private A a; 

    public B() { 
    } 

    @Autowired 
    public void setA(A a) { 
     this.a = a; 
    } 
} 

私はBと同様にAクラスを定義する場合、すべてがOKですが、上記の1がすでに動作するはずですので、なぜそれがないのですか?私はAクラスのコンストラクタで依存関係を取り除くことができない状況にあります。この場合、私は何ができますか?

EDIT: 私の例外::私は春3.2.1.RELEASEに

EDIT2使用しています

Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dependencyTest.A' defined in file [/home/adam/workspaces/testproject/target/classes/mypackage/test/DependencyTest$A.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [mypackage.test.DependencyTest$B]: : Error creating bean with name 'dependencyTest.B': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void mypackage.test.DependencyTest$B.setA(mypackage.test.DependencyTest$A); nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'dependencyTest.A': Requested bean is currently in creation: Is there an unresolvable circular reference?; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dependencyTest.B': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void mypackage.test.DependencyTest$B.setA(mypackage.test.DependencyTest$A); nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'dependencyTest.A': Requested bean is currently in creation: Is there an unresolvable circular reference? 
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:730) 
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:196) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1049) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:953) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:490) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:626) 
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932) 
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479) 
    at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:84) 
    at mypackage.test.DependencyTest.main(DependencyTest.java:10) 
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dependencyTest.B': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void mypackage.test.DependencyTest$B.setA(mypackage.test.DependencyTest$A); nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'dependencyTest.A': Requested bean is currently in creation: Is there an unresolvable circular reference? 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:288) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1120) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:522) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:891) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:834) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:749) 
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:795) 
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:723) 
    ... 14 more 
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void mypackage.test.DependencyTest$B.setA(mypackage.test.DependencyTest$A); nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'dependencyTest.A': Requested bean is currently in creation: Is there an unresolvable circular reference? 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:601) 
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87) 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:285) 
    ... 26 more 
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'dependencyTest.A': Requested bean is currently in creation: Is there an unresolvable circular reference? 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:327) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:217) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:891) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:834) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:749) 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:558) 
    ... 28 more 
+0

あなたのケースで正確なエラーを指摘していただければ幸いです。 – Taky

+0

@Takyスタックトレースを追加しました –

+0

静的内部クラスを使用せずに試しましたか?私はトップレベルのクラスを考えています... –

答えて

8

を私は春だけの関係のこのようなことを実現するのに十分な非常に賢いではないと思います解決不可能な循環参照のように見えないように特定の順序でロードする必要があります。これは通常、シングルトンインスタンスをキャッシュした後、シングルトンインスタンスを完全にポピュレートする前に、シングルトンインスタンスをキャッシュして、後で設定を完了することを知っているため、必要に応じてインスタンスを注入できるようにします。

Aを最初に作成しようとしていますが、Bなしで構築することもできないため、Aインスタンスをキャッシュできません。次に、Bを作成しようとすると、Aが必要だとわかりますが、Aを作成する過程にあることがわかりますが、依存関係に使用するキャッシュされたインスタンスがないため、失敗します。 @DependsOn("dependencyTest.B")のようなもので最初にBインスタンスを作成するように強制する必要があります。したがって、Aを必要とせずにBを構築することができるため、シングルトンキャッシングが可能です.Aを作成するときに、未投入のBインスタンスが使用可能になります。

+0

これは良い解決策です。しかし、私の例では、@DependsOn( "b") 'や@DependsOn(" dependencyTest.B ")さえ間違えてしまいました(これらが内部クラスであることがわかるスタックトレースを見た場合) 'A'クラスの' @Component'アノテーションの隣に追加されました –

+0

さらに、私が既に報告しているように(https://jira.springsource.org/browse/SPR-10349)、逆の状況は問題なく動作します。上記の私のコメントに従って答えを変更した場合、私はこの特別なケースの回避策としてそれを受け入れることができます(誰かが私に何か良いものを提供しない限り:)) –

+0

'@ DependsOn'で間違った名前を残して申し訳ありません。今修正されました。 Springが検出して処理できるように見えるので、私はそのバグに投票しました。 –

2

最初にBeanをインスタンス化し、だからこそあなたはこの状況に直面しています。 Aをインスタンス化する場合は、Bが必要です。

インスタンス生成フェーズは依存関係を追加せずに行われるため、コンストラクタの代わりにセッタを使用すると、この問題が解決されます。

+0

一方はセッター注入を使用しているので、解決できない問題ではありません。 [私の答え](http://stackoverflow.com/a/15194949/839646)を参照してください。 –

+0

「解決できない」と私は言ったのですか?彼が尋ねると、私はちょうどその問題とそれがなぜ起こるのかを説明しました。 –

関連する問題