10

我已经阅读过,以避免循环依赖,我可以@Autowired在设置器而不是构造器上使用。

如果是这样,为什么会失败?

@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;
    }
}

如果我以A类似的方式定义类B,一切都很好,但是上面的应该已经可以工作了,那为什么不行呢?我处于无法摆脱A类构造函数中的依赖关系的情况。在这种情况下我能做什么?

编辑:我正在使用 Spring 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
4

2 回答 2

8

我认为 Spring 还不够聪明,无法意识到必须以特定顺序加载这种关系,以避免看起来像无法解析的循环引用。它通常通过在构造它们之后但在完全填充它们之前缓存单例实例来处理循环引用,以便它可以在需要的地方注入实例,即使它还没有填充,因为它知道它将在稍后完成设置。

发生的事情是它首先尝试创建 A,但它甚至无法在没有 B 的情况下构造一个,因此它无法缓存 A 实例。然后它尝试创建一个 B 并看到它需要一个 A,但它知道它正在创建 A 的过程中但没有用于依赖项的缓存实例,所以它失败了。您需要强制它首先使用类似 a 的东西创建 B 实例@DependsOn("dependencyTest.B")。然后可以进行单例缓存,因为可以在不需要 A 的情况下构造 B,因此在创建 A 时将可以使用未填充的 B 实例。

于 2013-03-04T05:10:39.800 回答
2

bean 首先被实例化,然后相互注入。这就是你面临这种情况的原因。当A被实例化时,它需要B.

使用 setter 而不是构造函数可以解决这个问题,因为实例化阶段是在不添加依赖项的情况下完成的。

于 2013-03-04T05:22:09.283 回答