Вопрос или проблема
Мне нравится строгая типизация и возможности рефакторинга в @ConfigurationProperties
. Я хочу использовать условные бины, но не хочу использовать @ConditionalOnProperty
, потому что он требует указания имени свойства в сыром виде.
Я попробовал следующий подход
@Conditional(SecurityEnabledCondition.class)
@Bean ...
public class SecurityEnabledCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
ClientProperties clientProperties = context.getBeanFactory().getBean(ClientProperties.class);
return clientProperties.isSecured();
}
}
Но бин не найден, так как Condition
не предназначен для взаимодействия с бинами. Как использовать @ConfigurationProperties с @Conditional в Spring?
Ответ или решение
Для использования @ConfigurationProperties
вместе с @Conditional
в Spring, нужно учитывать, что @Conditional
не может взаимодействовать напрямую с бинами, так как он работает на этапе создания контекста. Тем не менее, есть способ достичь желаемого результата, не прибегая к строковым именам свойств.
Ниже приведены шаги, которые помогут вам использовать @ConfigurationProperties
в комбинации с @Conditional
.
Шаг 1: Определите ваш класс @ConfigurationProperties
Создайте класс для хранения свойств конфигурации, который будет использовать аннотацию @ConfigurationProperties
:
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "client")
public class ClientProperties {
private boolean secured;
// Геттеры и сеттеры
public boolean isSecured() {
return secured;
}
public void setSecured(boolean secured) {
this.secured = secured;
}
}
Шаг 2: Создайте условие для вашего бина
Создайте класс, реализующий интерфейс Condition
, который будет проверять состояние вашего бина ClientProperties
.
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.stereotype.Component;
@Component
public class SecurityEnabledCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// Получаем бин ClientProperties из контекста
ClientProperties clientProperties = context.getBeanFactory().getBean(ClientProperties.class);
return clientProperties.isSecured();
}
}
Шаг 3: Используйте условие в вашем бине
Теперь вы можете использовать @Conditional
для создания условия на основе ClientProperties
в вашем конфигурационном классе:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SecurityConfiguration {
@Conditional(SecurityEnabledCondition.class)
@Bean
public SecurityService securityService() {
return new SecurityService();
}
}
Шаг 4: Настройка свойств
Не забудьте добавить ваши свойства в файл конфигурации (например, application.yml
или application.properties
):
client:
secured: true
Пример класса защиты
Пример класса SecurityService
, который вы создаете условно:
public class SecurityService {
// Реализация сервиса безопасности
}
Заключение
Теперь, когда вы запускаете приложение, если свойство secured
в ClientProperties
установлено в true
, то будет создан бин SecurityService
. Этот подход позволяет вам использовать @ConfigurationProperties
для конфигурации и добавлять условия на основе значений этих свойств, обеспечивая типизацию и легкость рефакторинга.