Как работает аннотация @Conditional в Spring?

«Как работает аннотация @Conditional в Spring?» — вопрос из категории Spring, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

@Conditional — это базовая аннотация Spring для условной регистрации бинов в контексте приложения. Условие определяется реализацией интерфейса Condition.

Принцип работы: Spring проверяет условие, заданное в @Conditional, и регистрирует бин только если оно выполняется (matches() возвращает true).

Пример с пользовательским условием:

@Configuration
public class FeatureConfig {
    // Бин зарегистрируется, только если выполнится MyFeatureCondition
    @Bean
    @Conditional(MyFeatureCondition.class)
    public MyService myService() {
        return new MyService();
    }
}

public class MyFeatureCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        // Проверяем наличие системного свойства или переменной окружения
        String featureFlag = context.getEnvironment().getProperty("my.feature.enabled");
        return "true".equalsIgnoreCase(featureFlag);
    }
}

Встроенные производные аннотации (более удобные): Spring Boot предоставляет множество готовых аннотаций на основе @Conditional:

  • @ConditionalOnProperty: Зависит от значения свойства.
    @Bean
    @ConditionalOnProperty(name = "cache.provider", havingValue = "redis")
    public CacheManager redisCacheManager() { ... }
  • @ConditionalOnClass / @ConditionalOnMissingClass: Зависит от наличия/отсутствия класса в classpath.
    @Bean
    @ConditionalOnClass(name = "com.example.SomeClient")
    public SomeService someService() { ... }
  • @ConditionalOnBean / @ConditionalOnMissingBean: Зависит от наличия/отсутствия другого бина в контексте.
    @Bean
    @ConditionalOnMissingBean(DataSource.class)
    public DataSource inMemoryDataSource() { ... }
  • @ConditionalOnWebApplication / @ConditionalOnNotWebApplication: Зависит от типа приложения.

Основное применение: Создание автоконфигураций, включение фич по флагам, выбор реализации в зависимости от окружения.