Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Виды @Conditional аннотаций в Spring
@Conditional — это мощный механизм в Spring Boot для условной регистрации Bean'ов. Spring предоставляет множество встроенных аннотаций для различных условий, а также позволяет создавать свои условия.
1. @ConditionalOnClass
Bean регистрируется, если класс присутствует в classpath:
@Configuration
public class MyConfiguration {
// Этот Bean создаётся только если Jackson присутствует в зависимостях
@Bean
@ConditionalOnClass(name = "com.fasterxml.jackson.databind.ObjectMapper")
public JacksonJsonProvider jacksonJsonProvider() {
return new JacksonJsonProvider();
}
// Или используя класс напрямую
@Bean
@ConditionalOnClass(Jackson2ObjectMapperBuilder.class)
public ObjectMapper objectMapper() {
return new ObjectMapper();
}
}
Когда использовать: Для опциональной интеграции с внешними библиотеками.
2. @ConditionalOnMissingClass
Противоположность @ConditionalOnClass — Bean создаётся, если класса нет:
@Configuration
public class FallbackConfiguration {
// Если Jackson не установлен, используем GSON
@Bean
@ConditionalOnMissingClass("com.fasterxml.jackson.databind.ObjectMapper")
public GsonJsonProvider gsonJsonProvider() {
return new GsonJsonProvider();
}
}
3. @ConditionalOnBean
Bean регистрируется, если другой Bean уже существует:
@Configuration
public class DataSourceConfiguration {
// Создаём HikariCP DataSource только если DataSource Bean уже существует
@Bean
@ConditionalOnBean(DataSourceProperties.class)
public DataSource hikariDataSource(DataSourceProperties props) {
HikariConfig config = new HikariConfig();
config.setJdbcUrl(props.getUrl());
return new HikariDataSource(config);
}
}
4. @ConditionalOnMissingBean
Bean регистрируется, если другого Bean нет — очень часто используется:
@Configuration
public class RestTemplateConfiguration {
// Если RestTemplate Bean не создан вручную, создаём дефолтный
@Bean
@ConditionalOnMissingBean
public RestTemplate restTemplate() {
return new RestTemplate();
}
// Или указываем конкретный тип
@Bean
@ConditionalOnMissingBean(type = "org.springframework.web.client.RestTemplate")
public RestTemplate defaultRestTemplate() {
return new RestTemplate(new HttpComponentsClientHttpRequestFactory());
}
}
5. @ConditionalOnProperty
Bean регистрируется в зависимости от значения property в конфигурационном файле:
# application.yml
app:
cache:
enabled: true
type: redis
@Configuration
public class CacheConfiguration {
// Включаем кэширование только если app.cache.enabled=true
@Bean
@ConditionalOnProperty(
name = "app.cache.enabled",
havingValue = "true"
)
public CacheManager cacheManager() {
return new RedisCacheManager(...);
}
// Проверяем наличие и значение property
@Bean
@ConditionalOnProperty(
name = "app.cache.type",
havingValue = "redis",
matchIfMissing = false // Требует наличие property
)
public RedisTemplate<String, Object> redisTemplate() {
return new RedisTemplate<>();
}
}
6. @ConditionalOnResource
Bean регистрируется, если ресурс (файл) присутствует в classpath:
@Configuration
public class LicenseConfiguration {
// Создаём Bean только если файл лицензии существует
@Bean
@ConditionalOnResource(resources = "classpath:license.txt")
public LicenseValidator licenseValidator() {
return new LicenseValidator("license.txt");
}
}
7. @ConditionalOnJava
Bean регистрируется в зависимости от версии Java:
@Configuration
public class JavaVersionConfiguration {
// Используем новый API только на Java 11+
@Bean
@ConditionalOnJava(JavaVersion.ELEVEN_OR_NEWER)
public ModernHttpClient modernHttpClient() {
return new ModernHttpClient(); // Использует HttpClient из Java 11
}
// Старый API для Java 8-10
@Bean
@ConditionalOnJava(range = Range.UP_TO_INCLUSIVE, value = JavaVersion.TEN)
public LegacyHttpClient legacyHttpClient() {
return new LegacyHttpClient(); // Использует HttpURLConnection
}
}
8. @ConditionalOnWebApplication
Bean регистрируется, если приложение является web-приложением:
@Configuration
@ConditionalOnWebApplication
public class WebSecurityConfiguration {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(auth -> auth.anyRequest().authenticated());
return http.build();
}
}
9. @ConditionalOnNotWebApplication
Противоположность — Bean для неWeb-приложений:
@Configuration
@ConditionalOnNotWebApplication
public class BatchConfiguration {
@Bean
public JobLauncher jobLauncher(JobRepository jobRepository) {
SimpleJobLauncher launcher = new SimpleJobLauncher();
launcher.setJobRepository(jobRepository);
return launcher;
}
}
10. Собственные @Conditional
Можно создавать свои условия реализуя Condition:
// Определяем собственное условие
public class ProductionCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String profile = context.getEnvironment().getProperty("spring.profiles.active");
return "production".equals(profile);
}
}
// Создаём свою аннотацию
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Conditional(ProductionCondition.class)
public @interface ConditionalOnProduction {
}
// Используем
@Configuration
@ConditionalOnProduction
public class ProductionConfiguration {
@Bean
public AnalyticsService analyticsService() {
return new ProductionAnalytics();
}
}
11. @Profile
Связана с условной регистрацией, но через профили:
@Configuration
@Profile("development")
public class DevelopmentConfiguration {
@Bean
public DataSource devDataSource() {
return new EmbeddedDatabaseBuilder()
.setType(H2)
.build();
}
}
@Configuration
@Profile("production")
public class ProductionConfiguration {
@Bean
public DataSource prodDataSource() {
return new HikariDataSource(...);
}
}
12. Комбинирование условий
@Configuration
public class AdvancedConfiguration {
// Все условия должны быть истинны (AND)
@Bean
@ConditionalOnClass(DataSource.class)
@ConditionalOnProperty(
name = "spring.datasource.enabled",
havingValue = "true"
)
@ConditionalOnMissingBean(DataSource.class)
public DataSource dataSource() {
return new HikariDataSource();
}
}
Практический пример: Auto-configuration
// spring-boot-autoconfigure
@Configuration
@ConditionalOnClass(DataSource.class)
@ConditionalOnMissingBean(DataSource.class)
@ConditionalOnProperty(
prefix = "spring.datasource",
name = "url"
)
public class DataSourceAutoConfiguration {
@Bean
public DataSource dataSource(DataSourceProperties properties) {
return createDataSource(properties);
}
}
Это как Spring Boot автоматически добавляет DataSource, если в pom.xml есть драйвер и в application.yml есть spring.datasource.url.
Порядок применения условий
1. @ConditionalOnClass — classpath
2. @ConditionalOnBean — другие Beans
3. @ConditionalOnProperty — конфигурация
4. @ConditionalOnResource — файлы
5. @ConditionalOnJava — версия JVM
6. Кастомные Condition
Когда использовать
- @ConditionalOnClass — опциональные библиотеки
- @ConditionalOnMissingBean — дефолтные реализации
- @ConditionalOnProperty — включение/отключение функций
- @Profile — разные конфигурации для разных окружений
- @ConditionalOnWebApplication — разная конфигурация для Web/Batch
Все эти аннотации работают вместе, создавая гибкую и мощную систему конфигурации в Spring Boot, позволяя автоматически регистрировать нужные Bean'ы в зависимости от контекста приложения.