2016-06-21 19 views
-3

Следующий код не вызывает StackOverflowError ошибку, не любой здравомыслящий сообщение:Почему продублированный bean-компонент вызывает StackOverflowError, но не вызывает никаких разумных ошибок?

import org.springframework.context.annotation.AnnotationConfigApplicationContext; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 

public class DuplicateBeans2 { 

    public static class MyClass { 
    } 


    @Configuration 
    public static class Config1 { 

     @Bean 
     MyClass myClass() { 
     return myClass(); 
     } 
    } 

    @Configuration 
    public static class Config2 { 

     @Bean 
     MyClass myClass() { 
     return myClass(); 
     } 
    } 

    public static void main(String[] args) { 

     new AnnotationConfigApplicationContext(Config1.class, Config2.class); 

    } 

} 

Почему? Разве это не плохой дизайн, чтобы не сообщать об этом явно?

UPDATE

К сожалению люди, это моя вина, я просто написал неправильно:

 @Bean 
     MyClass myClass() { 
     return new MyClass(); 
     } 
+0

Не могли бы вы еще разместить трассировку стека? – Timo

+3

Ваши рекурсивные вызовы в 'myClass()' заполнят стек вызовов и останавливают все. Это не имеет никакого отношения к весне. Попробуйте вызвать это непосредственно из 'public static void main()' method, и вы получите тот же результат. –

ответ

1

Во-первых, здесь проблема не имеет ничего общего с повторяющимися бобов. Реальная проблема заключается в том, что метод myClass() безоговорочно вызывает себя. Вы получите тот же эффект, с этим классом:

public class Test { 
     public static void main(String[] args) { 
      main(args); 
     } 
    } 

Почему?

Вы получаете эту проблему, потому что myClass() себя безоговорочно звонки ...

Разве это плохой дизайн, чтобы не сообщать об этом в явном виде?

Я бы так не сказал. Нельзя ожидать, что компилятор Java предупредит обо всех ошибках, которые программист мог бы сделать. Я бы сказал, что это «не стоит» в этом случае, потому что:

  • ошибка является необычной, и
  • результат ошибки является исключением, что легко для не-начинающего программиста для диагностики

Тогда рассмотрим следующий пример:

public class A { 

     public void test() { 
      recurse(); 
     } 

     public void recurse() { 
      recurse(); 
     } 
    } 

Теперь добавьте это:

public class B extends A { 
     @Override 
     public void recurse() { 
      // do nothing 
     } 
    } 

Если вы вызываете test на экземпляр A, вы получите StackOverflowError. Если вы вызовете это на примере B, вы не будете. Если компилятор предупредил, что A.recurse() был ошибочным, это было бы неправильно.