春季假阳性循环依赖报道

时间:2015-04-01 15:11:24

标签: java spring-mvc

当依赖顺序如下所示时,

Spring会报告误报循环依赖性错误

  • FactoryBean依赖于List(示例AnimalFeeder)
  • AnimalFeeder依赖于字符串列表。

有趣的事情

  1. 当弹簧实例化顺序改变时未观察到问题Ie)FactoryBean出现在AnimalFeeder之前。但是当AnimalFeeder出现在FactoryBean之前时就会出现这个问题。
  2. 仅在涉及FactoryBean时才会发生这种情况。当使用简单的bean类而不是FactoryBean时,没有观察到问题。
  3. 这是源代码

    public interface Feeder {
        void feed();
    }
    
    public class AnimalFeederImpl implements Feeder {
      private List<String> feedingTypes;
      public AnimalFeederImpl(List<String> feedingTypes) {
        this.feedingTypes = feedingTypes;
      }
      @Override
      public void feed() {
        //feed here
      }
    }
    
    public class FeederManager {
      private final List<Feeder> feeders;
      public FeederManager(List<Feeder> feeders) {
          this.feeders = feeders;
      }
    
      //This method will trigger the feeding for every 4 hours
      public void triggerFeeding() { 
      }
    }
    
    
    public class FeederFactory implements FactoryBean, InitializingBean {
      private List<Feeder> feeders;
      private FeederManager feederManager;
      public FeederFactory(List<Feeder> feeders) {
          this.feeders = feeders;
      }
    
      @Override
      public void afterPropertiesSet() throws Exception {
          feederManager = new FeederManager(feeders);
      }
    
      public static void main(String args[]){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext();
        context.setAllowBeanDefinitionOverriding(false);
        context.setConfigLocation("test-application-context.xml");
        context.refresh();
      }
    }
    

    这是上下文文件                     

     <bean id="water" class="java.lang.String">
        <constructor-arg value="water"/>
     </bean>
     <bean id="animalFeeder" class="org.test.spring.autowire.impl.AnimalFeederImpl" autowire="constructor"/> 
     <bean id="animalFeeder" class="org.test.spring.autowire.impl.AnimalFeederImpl" autowire="constructor"/> 
     <bean id="feederMgr" class="org.test.spring.autowire.impl.FeederFactory" autowire="constructor"/>
    

    谢谢!

1 个答案:

答案 0 :(得分:1)

问题(在您看似不完整的示例中也会导致编译错误)是您的FeederFactory实现了类型FactoryBean

public class FeederFactory implements FactoryBean, InitializingBean {

当Spring尝试使用其构造函数

实例化AnimalFeederImpl bean时
public AnimalFeederImpl(List<String> feedingTypes) {
    this.feedingTypes = feedingTypes;
}

它需要首先构造List<String>参数。为此,它需要扫描类型为String的bean的上下文。它确实知道waterString类型的bean,因为它在XML配置中以这种方式声明。它确定AnimalFeederImpl不是String类型的bean,因为它的类类型也是声明的。

然而,对于FeederFactory,它有点不同。通过将该类声明为FactoryBean的子类,您可以告诉Spring该bean可以创建另一种类型的bean。要找出它是什么类型,Spring需要实例化FeederFactory类型并使用其getObjectType方法。

但它的实例化要求Spring自动装载

public FeederFactory(List<Feeder> feeders) {

要求它实例化已经在构造中的AnimalFeederImpl并且整个事情都失败并带有循环依赖。