2013-03-03 2 views
8

원형 의존성을 피하기 위해 나는 생성자 대신 setter에 @Autowired을 사용할 수 있습니다.setter를 사용한 스프링 순환 의존성

그렇다면 왜 이것이 실패합니까?

@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 클래스를 정의하면, 모든 것이 괜찮습니다,하지만 위가 이미 작동합니다, 왜 그렇지? 나는 A 클래스의 생성자에서 종속성을 제거 할 수없는 상황에 있습니다. 이 경우 무엇을 할 수 있습니까?

이 편집 : 나는 봄 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 인스턴스를 생성해야합니다. 그러면 B가 A를 필요로하지 않고 구성 될 수 있기 때문에 싱글 톤 캐싱이 발생할 수 있으므로 A를 만들 때 채워지지 않은 B 인스턴스를 사용할 수 있습니다.

+0

좋은 해결 방법이다. 그러나 당신은 순서를 오해했습니다, 나의 예제에서는'@DependsOn ("b")'또는'@DependsOn ("dependencyTest.B")이 될 것입니다 (stacktrace를 들여다 보면 이것이 내부 클래스임을 알 수 있습니다). 'A' 클래스의'@Component' 주석 옆에 추가 –

+0

그리고 이미 내가보고 한 버그 (https://jira.springsource.org/browse/SPR-10349)에서 이미 언급했듯이 상황이 문제없이 작동합니다. 그래서 위의 내 의견에 따라 답변을 바꾸면 누군가가 저에게 더 나은 것을 제공하지 않는 한이 특별한 경우에 대한 해결책으로 받아 들일 수 있습니다 :) –

+0

그래,'@ DependsOn'에서 잘못된 이름을 유감스럽게 생각합니다. 이제 해결되었습니다. Spring이 감지하고 처리 할 수 ​​있어야하는 버그와 같아서 그 버그를 표결했습니다. –

2

콩은 먼저 인스턴스화 된 다음 서로 주입됩니다. 그래서 당신은이 상황에 직면 해 있습니다. A이 인스턴스화 될 때 B이 필요합니다.

생성자 대신에 setter를 사용하면 종속성을 추가하지 않고 인스턴스화 단계가 완료되므로이 문제가 해결됩니다.

+0

한 쪽에서는 세터 주입을 사용하므로 해결할 수없는 문제는 아닙니다. [내 대답] (http://stackoverflow.com/a/15194949/839646)을 참조하십시오. –

+0

"해결할 수 없다"고 했습니까?그가 물었을 때, 나는 그 문제와 왜 그것이 일어 났는지 설명했다. –