Spring Javaconfig межбобовых зависимостей

Просматривая справочную документацию по Spring Javaconfig http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/beans.html я нашел некоторые запутанные части...

В разделе "5.12.4 Использование аннотации @Configuration" говорится:

"Когда @Beans имеют зависимости друг от друга, выразить эту зависимость так же просто, как заставить один метод bean вызывать другой:

@Configuration
public class AppConfig {
    @Bean
    public Foo foo() {
        return new Foo(bar());
    }
    @Bean
    public Bar bar() {
        return new Bar();
    }
}

В приведенном выше примере компонент foo получает ссылку на bar с помощью инжектора конструктора."

Хорошо, если все не имеет состояния, это может не иметь большого значения, но если у вас есть конфигурация выше, а затем в вашем приложении выполните:

@Autowired 
private Foo foo;

@Autowired 
private Bar bar;

проверяя hashCodes 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 компонента одного типа, ClientService, без отличительных свойств, поэтому получите исключение

org.springframework.beans.factory.NoUniqueBeanDefinitionException: 
No qualifying bean of type [.....] is defined: 
expected single matching bean but found 2

Но даже если мы немного изменим пример и дадим первые 2 бина разных типов,

@Bean
public ClientService1 clientService1() {...clientDao()...}
@Bean
public ClientService2 clientService2() {...clientDao()...}
@Bean
public ClientDao clientDao() {
    return new ClientDaoImpl();
}

это по-прежнему неверно, поскольку - вопреки тому, что говорится в тексте - мы все равно создали бы 3 разных экземпляра ClientDaoImpl при автоматической разводке всех 3 бинов.

Опять же, я что-то упускаю или документация действительно так плоха, как мне кажется?

РЕДАКТИРОВАТЬ: Добавлено демо, которое продемонстрирует проблему, которую я вижу:

https://github.com/rop49/demo

Бин ServiceA и два бина ServiceB1, ServiceB2, которые конструктор внедряет ServiceA.

Затем два тестовых класса Config01Test и Config02Test, которые идентичны, за исключением конфигураций. Первый тест PASSES, второй FAILS из-за уникальности утверждает.

2 ответа

Решение

Проверьте, что у вас есть @Configuration аннотации к вашему классу конфигурации. По крайней мере, в вашей демоверсии они отсутствуют Config01 а также Config02 классы. Если я добавлю их в эти классы, тесты пройдут.

Я сам не тестировал пример. Это должно убедиться, что у вас есть только один экземпляр Bar в полном контексте приложения.

@Configuration
public class AppConfig {
    @Bean
    public Foo foo(Bar bar) {
        return new Foo(bar);
    }
    @Bean
    public Bar bar() {
        return new Bar();
    }
}
Другие вопросы по тегам