@Conditional и @Profile

Оба механизма решают, будет ли зарегистрирован BeanDefinition. Решение принимается при построении контекста, а не при каждом вызове метода.

@Profile

@Configuration
@Profile("dev")
class DevConfiguration {}

Профиль — именованная группа конфигурации. Выражения поддерживают логические условия, например prod & !migration.

Активировать профиль можно свойством spring.profiles.active, но лучше, чтобы способ активации был виден в конфигурации окружения. Не следует зашивать production secrets в profile-файл.

@Conditional

@Bean
@ConditionalOnMissingBean(Clock.class)
Clock systemClock() {
    return Clock.systemUTC();
}

В Spring Boot часто используются:

  • @ConditionalOnClass;
  • @ConditionalOnMissingBean;
  • @ConditionalOnBean;
  • @ConditionalOnProperty;
  • @ConditionalOnWebApplication.

Порядок имеет значение: condition видит definitions, зарегистрированные к этому моменту. Auto-configuration проектируют так, чтобы пользовательский bean мог её заменить.

Как диагностировать

Если bean отсутствует:

  1. проверить активные profiles;
  2. проверить property name, prefix и значение;
  3. посмотреть condition evaluation report;
  4. убедиться, что конфигурация импортирована;
  5. проверить наличие класса и конкурирующего bean;
  6. не путать «bean не создан» с «bean создан, но proxy другого типа».

Вопросы для повторения

  1. @Profile проверяется при каждом вызове? Нет, при регистрации контекста.
  2. Чем profile отличается от property condition? Profile — крупная именованная группа, property condition — точное условие настройки.
  3. Что делает @ConditionalOnMissingBean? Регистрирует конфигурацию, только если подходящего bean ещё нет.
  4. Можно ли использовать profile для секрета? Нет, профиль выбирает конфигурацию, секрет приходит из защищённого источника.
  5. Почему условие трудно отлаживать? Результат зависит от classpath, properties, порядка и уже зарегистрированных definitions.

Связано: Профили Sping и Maven, Spring Boot, Основные аннотации Spring.