Ответ
Аннотации @ConditionalOn... в Spring Boot — это часть механизма автоконфигурации. Они позволяют условно регистрировать бины или конфигурационные классы в контексте приложения в зависимости от состояния среды (наличие класса, свойства, бина и т.д.).
Распространённые аннотации:
@ConditionalOnClass— если указанный класс присутствует в classpath.@ConditionalOnMissingClass— если класс отсутствует.@ConditionalOnBean/@ConditionalOnMissingBean— если бин присутствует/отсутствует.@ConditionalOnProperty— если определённое свойство имеет заданное значение.@ConditionalOnWebApplication/@ConditionalOnNotWebApplication— в зависимости от типа приложения.
Пример 1: Создание бина только при наличии класса в classpath
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyAutoConfiguration {
// Бин будет создан, только если в classpath есть класс 'com.example.ExternalService'
@Bean
@ConditionalOnClass(name = "com.example.ExternalService")
public MyService myService() {
return new MyService();
}
}
Пример 2: Условная конфигурация на основе свойства application.yml
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FeatureConfiguration {
// Бин будет зарегистрирован, только если свойство 'app.feature.enabled' равно 'true'
@Bean
@ConditionalOnProperty(prefix = "app.feature", name = "enabled", havingValue = "true")
public AdvancedService advancedService() {
return new AdvancedService();
}
}
# application.yml
app:
feature:
enabled: true # Если false, бин advancedService не будет создан.
Пример 3: Создание бина по умолчанию, если другой отсутствует
@Configuration
public class CacheConfig {
// Создаём бин defaultCache, только если бин с именем 'redisCache' НЕ найден.
@Bean
@ConditionalOnMissingBean(name = "redisCache")
public Cache defaultCache() {
return new SimpleInMemoryCache();
}
}
Зачем это нужно? Позволяет Spring Boot автоматически настраивать приложение в зависимости от добавленных зависимостей (spring-boot-starter-*) и параметров, избегая конфликтов и лишней конфигурации.
Ответ 18+ 🔞
Да ты посмотри, какие у них, блядь, штуки придумали, эти спринговые мудрецы! Аннотации @ConditionalOn... — это ж как хитрая жопа, которая решает, что в твоём приложении жить будет, а что — в пизду отправится. Автоконфигурация, ёпта, магия!
Основные приколюхи:
@ConditionalOnClass— работает, только если нужный класс где-то в закромах classpath'а валяется.@ConditionalOnMissingClass— наоборот, сработает, если класса нихуя нет.@ConditionalOnBean/@ConditionalOnMissingBean— тут уже смотрят, есть ли в контексте какой-то конкретный бин или нет. Чисто интриги, блядь.@ConditionalOnProperty— это вообще песня. Всё от настроек вapplication.ymlзависит. Сказалtrue— живёшь, сказалfalse— иди нахуй.@ConditionalOnWebApplication/@ConditionalOnNotWebApplication— чтобы понимать, веб-приложение у тебя или консольная поделка.
Пример первый: Хитрый бин, который прячется
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyAutoConfiguration {
// Этот сервис вылезет наружу, только если найдёт в classpath'е 'com.example.ExternalService'.
// Нет класса — нет сервиса. Всё просто, как три копейки.
@Bean
@ConditionalOnClass(name = "com.example.ExternalService")
public MyService myService() {
return new MyService();
}
}
Пример второй: Включаем фичи через конфиг, а не кувалдой
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FeatureConfiguration {
// Смотри, какая хитрая жопа: пока ты в настройках не напишешь 'app.feature.enabled=true',
// этот `AdvancedService` даже не подумает рождаться. Сидит, блядь, в засаде.
@Bean
@ConditionalOnProperty(prefix = "app.feature", name = "enabled", havingValue = "true")
public AdvancedService advancedService() {
return new AdvancedService();
}
}
# application.yml
app:
feature:
enabled: true # Вот тут написал 'true' — и всё, поздравляю, бин на месте. Написал бы 'false' — и хуй с горы.
Пример третий: Запасной аэродром на случай пиздеца
@Configuration
public class CacheConfig {
// Это гениально, ёпта! Спринг смотрит: "А есть тут у нас бин с именем 'redisCache'?"
// Если нет — охуенно, создаём простенький `defaultCache`. Если вдруг какой-то умник уже зарегистрировал 'redisCache' —
// то мы, скромные такие, отходим в сторонку. Никаких конфликтов, всё цивильно.
@Bean
@ConditionalOnMissingBean(name = "redisCache")
public Cache defaultCache() {
return new SimpleInMemoryCache();
}
}
А нахуя это всё? Да чтобы голова не болела, вот нахуя! Добавил ты какую-нибудь зависимость spring-boot-starter-что-то-там — а фреймворк сам, как хитрая мартышлюшка, уже подобрал кучу умных @ConditionalOn... аннотаций в своих автоконфигах. Они смотрят: "А, так у тебя есть библиотека для Redis? О, отлично, вот тебе бин redisCache. Нету? Ну и хуй с тобой, живи без него". Волшебство, блядь, а не разработка.