ConditionalOnMissingBean
Неприятным сюрпризом оказалось поведение аннотации @ConditionalOnMissingBean
. Казалось бы, название говорит о том, что бин добавляется в контекст только тогда, когда нет бина с таким же классом (или с классом, который указан в параметре аннотации).
Т.е. если есть
@Configuration
class MainConfiguration
@ConditionalOnMissingBean(MainConfiguration::class)
@Configuration
class TestConfiguration
то TestConfiguration
загрузится только в случае, если в контексте нет MainConfiguration
. Однако если переименовать TestConfiguration
→ ConfigurationTest
, то будут загружены обе конфигурации. WTF, переименование класса ломает функциональность?
На самом деле, все очень просто: загрузка бинов в контекст по умолчанию производится в лексикографическом порядке, а @ConditionalOnMissingBean
смотрит только на контекст, загруженный на данный момент, и во втором случае бин MainConfiguration
действительно пока еще не создан при загрузке ConfigurationTest
. Конечно, документация явно говорит об этом и предлагает использовать @ConditionalOnMissingBean
только для автоконфигураций. Решить эту проблему можно явной аннотацией @Order
или профилями, но сделать это можно только для контролируемых классов. И ради тестов такое делать — перебор. Но ни через какой @Conditional
это сделать не получится, т.к. он не влияет на порядок загрузки бинов.