Просмотрите справочную документацию Spring Javaconfig http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/beans.html Я нашел несколько запутанных частей...
В разделе "5.12.4 Использование аннотации @Configuration" говорится:
"Когда @Beans зависят друг от друга, выразить эту зависимость так же просто, как заставить один метод компонента вызывать другой:
@Configuration
public class AppConfig {
@Bean
public Foo foo() {
return new Foo(bar());
}
@Bean
public Bar bar() {
return new Bar();
}
}
В приведенном выше примере bean-компонент foo получает ссылку на bar посредством внедрения конструктора."
Ну, если все без состояния, то может это и не имеет большого значения, но если у вас есть конфиг выше, а затем в вашем приложении сделайте:
@Autowired
private Foo foo;
@Autowired
private Bar bar;
проверяя хэш-коды bean-компонентов, выясняется, что ваша частная переменная bar будет ссылаться на другой экземпляр Bar, чем тот, который используется foo, что, вероятно, не соответствует вашим ожиданиям, верно?
Я бы сказал, что нормальный шаблон должен быть таким:
@Configuration
public class AppConfig {
@Bean
public Bar bar() {
return new Bar();
}
@Autowired Bar bar;
@Bean
public Foo foo() {
return new Foo(bar);
}
}
Теперь, когда вы автоматически подключаете оба компонента в своем приложении, вы создаете только один экземпляр Bar.
Я что-то упустил или я прав, что документация здесь ненадежная?
Далее, в разделе "Дополнительная информация о внутренней работе конфигурации на основе Java" похоже, что они пытаются "прояснить" этот вопрос:
@Configuration
public class AppConfig {
@Bean
public ClientService clientService1() {
ClientServiceImpl clientService = new ClientServiceImpl();
clientService.setClientDao(clientDao());
return clientService;
}
@Bean
public ClientService clientService2() {
ClientServiceImpl clientService = new ClientServiceImpl();
clientService.setClientDao(clientDao());
return clientService;
}
@Bean
public ClientDao clientDao() {
return new ClientDaoImpl();
}
}
Теперь, к сожалению, эта конфигурация даже не будет загружаться во время выполнения, потому что есть 2 bean-компонента одного типа, ClientService, без отличительных свойств, поэтому получите исключение
org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type [.....] is defined:
expected single matching bean but found 2
Но даже если мы немного изменим пример и дадим первым двум bean-компонентам разные типы,
@Bean
public ClientService1 clientService1() {...clientDao()...}
@Bean
public ClientService2 clientService2() {...clientDao()...}
@Bean
public ClientDao clientDao() {
return new ClientDaoImpl();
}
это по-прежнему неверно, поскольку - вопреки тому, что утверждается в тексте - мы все равно создадим 3 разных экземпляра ClientDaoImpl при автоподключении всех 3 bean-компонентов.
Опять же, я что-то упустил, или документация действительно так плоха, как мне кажется?
EDIT: добавлена демонстрация, демонстрирующая проблему, которую я вижу:
Компонент ServiceA и два компонента ServiceB1, ServiceB2, которые внедряют конструктор ServiceA.
Затем два тестовых класса Config01Test и Config02Test, которые идентичны, за исключением конфигураций. Первый тест ПРОЙДЕТ, второй НЕ ПРОЙДЕТ из-за проверки уникальности.
Bar
объекты? - person chrylis -cautiouslyoptimistic-   schedule 20.09.2014