В предыдущих базовых сообщениях блога о bean-компонентах основное внимание уделялось определению и использованию bean-компонентов, но есть ли какие-либо сценарии, в которых определяемые мной bean-компоненты не загружаются или определенные мной bean-компоненты загружаются только при выполнении определенных предварительных условий? А как же Бин?
В этом сообщении в блоге в основном будут представлены условные аннотации при загрузке bean-компонентов.@Conditional
Связанное использование
I. @Conditional
аннотация
Эта аннотация была введена в Spring4, и ее основная функция состоит в том, чтобы определить, выполняются ли условия, чтобы решить, следует ли инициализировать и регистрировать Bean-компонент в контейнере.
1. Определения
@Conditional
Аннотация определяется следующим образом, которая в основном использует интерфейс Condition, чтобы определить, выполняются ли условия, чтобы решить, следует ли загружать Bean.
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
Class<? extends Condition>[] value();
}
НижеCondtion
Можно сказать, что определение интерфейса является самой базовой записью.Все остальные условные аннотации, в конечном счете, расширяются за счет реализации этого интерфейса.
@FunctionalInterface
public interface Condition {
boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2);
}
В этом интерфейсе есть параметр поинтереснееConditionContext
, он содержит множество полезных объектов, которые можно использовать для получения большого количества информации, связанной с системой, для обогащения суждения о состоянии.Интерфейс определяется следующим образом
public interface ConditionContext {
// 获取Bean定义
BeanDefinitionRegistry getRegistry();
// 获取Bean工程,因此就可以获取容器中的所有bean
@Nullable
ConfigurableListableBeanFactory getBeanFactory();
// environment 持有所有的配置信息
Environment getEnvironment();
// 资源信息
ResourceLoader getResourceLoader();
// 类加载信息
@Nullable
ClassLoader getClassLoader();
}
2. Инструкция по применению
На небольшом примере кратко расскажите о том, как использовать Condition и@Conditional
Аннотация для достижения условной загрузки bean-компонентов
Во-первых, мы определяем класс, который случайным образом генерирует данные, его функция состоит в том, чтобы случайным образом генерировать некоторые данные.
public class RandDataComponent<T> {
private Supplier<T> rand;
public RandDataComponent(Supplier<T> rand) {
this.rand = rand;
}
public T rand() {
return rand.get();
}
}
В настоящее время мы предоставляем два вида bean-компонентов, сгенерированных случайными данными, но конкретный метод выбора необходимо выбирать в соответствии с конфигурацией, поэтому мы определяем bean-компоненты следующим образом.
@Configuration
public class ConditionalAutoConfig {
@Bean
@Conditional(RandIntCondition.class)
public RandDataComponent<Integer> randIntComponent() {
return new RandDataComponent<>(() -> {
Random random = new Random();
return random.nextInt(1024);
});
}
@Bean
@Conditional(RandBooleanCondition.class)
public RandDataComponent<Boolean> randBooleanComponent() {
return new RandDataComponent<>(() -> {
Random random = new Random();
return random.nextBoolean();
});
}
}
Вышеупомянутая конфигурация, независимо от@Conditional
Содержание аннотации, просто посмотрите на определения двух bean-компонентов, один из которых определяет генерацию случайных чисел int, другой определяет генерацию случайных логических значений;
Но в нашей системе нам нужен только генератор случайных данных, выбираем по конфигурацииconditional.rand.type
Значение, чтобы выбрать, какое из них использовать, конфигурация выглядит следующим образом
# int 表示选择随机产生int数据; 非int 表示随机产生boolean数据
conditional.rand.type=int
Далее мы должны посмотреть, как добавляется это условие, то есть указанный выше класс конфигурацииConditionalAutoConfig
В содержании двух аннотаций реализованы оба классаCondition
интерфейс, как показано ниже
public class RandBooleanCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
String type = conditionContext.getEnvironment().getProperty("conditional.rand.type");
return "boolean".equalsIgnoreCase(type);
}
}
public class RandIntCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
String type = conditionContext.getEnvironment().getProperty("conditional.rand.type");
return "int".equalsIgnoreCase(type);
}
}
Вышеупомянутая реализация также относительно понятна, получите значение конфигурации, затем оцените и верните true/fase; если возвращается true, это означает, что условие выполнено, тогда бин может быть загружен; в противном случае бин не будет создан
3. Тестирование и проверка
Для приведенной выше конфигурации и реализации напишите тестовый класс следующим образом.
@RestController
@RequestMapping(path = "/conditional")
public class ConditionalRest {
@Autowired
private RandDataComponent randDataComponent;
@GetMapping(path = "/show")
public String show() {
String type = environment.getProperty("conditional.rand.type");
return randDataComponent.rand() + " >>> " + type;
}
}
Когда значением файла конфигурации является int, каждый доступ должен возвращать положительное целое число, как показано на следующем рисунке.
После изменения настроенного значения на логическое значение снова проверьте, как показано ниже.
II. ПРОДОЛЖЕНИЕ И РЕЗЮМЕ
Вышеприведенный тест демонстрирует случай выбора bean-компонента для внедрения через файл конфигурации.Если bean-компонент загружается посредством автоматического сканирования, можно ли его напрямую добавить в класс bean-компонента, чтобы решить, загружать его или нет?
1. Автоматически сканировать условную загрузку bean-компонентов
С точки зрения использования отличий от предыдущего нет, но аннотация размещена на конкретном классе, а также приведен пример, сначала определите бин
@Component
@Conditional(ScanDemoCondition.class)
public class ScanDemoBean {
@Value("${conditional.demo.load}")
private boolean load;
public boolean getLoad() {
return load;
}
}
Соответствующие условия оценки следующие, когда файл конфигурацииconditional.demo.load
При значении true эта конфигурация будет загружена, в противном случае она не будет создана.
public class ScanDemoCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
return "true".equalsIgnoreCase(conditionContext.getEnvironment().getProperty("conditional.demo.load"));
}
}
Тестовый класс аналогичен предыдущему, небольшое внимание — изменение необходимых условий при автоматическом внедрении, чтобы избежать ошибки, когда бин не существует.
@Autowired(required = false)
private ScanDemoBean scanDemoBean;
@GetMapping(path = "/scan")
public String showDemo() {
String type = environment.getProperty("conditional.demo.load");
if (scanDemoBean == null) {
return "not exists! >>>" + type;
} else {
return "load : " + scanDemoBean.getLoad() + " >>>" + type;
}
}
Если установлено значение true, bean-компонент должен существовать, следуйте приведенной выше логике else.
Когда конфигурация ложна, bean-компонент не будет загружен, и будет выполняться логика if.
2. Резюме
пройти через@Conditional
Аннотации подходятCondition
Интерфейс для принятия решения о создании и регистрации bean-компонента в контейнере Spring, чтобы обеспечить выборочную загрузку bean-компонентов.
А. Преимущества
Какова цель этого?
- Как выбрать, когда есть несколько бинов с одинаковым именем
- Решите случай, когда некоторые bean-компоненты создаются с другими зависимостями.
б. Дополнительные примечания
Вышеупомянутое может управлять созданием bean-компонентов, но через описанный выше процесс вы обнаружите, что он немного громоздкий.Есть ли способ упростить описанный выше процесс?
Просто используйте одну аннотацию, не реализуйте интерфейс Condtion самостоятельно, среда Spring предоставляет ряд связанных аннотаций, как показано в следующей таблице.
аннотация | иллюстрировать |
---|---|
@ConditionalOnSingleCandidate |
Возвращает true, когда существует bean-компонент данного типа и существует заданный тип, указанный как Primary |
@ConditionalOnMissingBean |
Возвращает true, если заданный тип, имя класса, аннотация, псевдоним не существует в beanFactory Связь между каждым типом или |
@ConditionalOnBean |
В отличие от вышесказанного, требуется, чтобы bean-компонент существовал |
@ConditionalOnMissingClass |
Возвращает true, если заданное имя класса не существует в пути к классам, и отношение между каждым типом равно и |
@ConditionalOnClass |
В отличие от вышесказанного, требуется, чтобы класс существовал |
@ConditionalOnCloudPlatform |
Верните True, когда настроенную CloudPlatform активируется |
@ConditionalOnExpression |
выражение spel выполняется как истинное |
@ConditionalOnJava |
Содержит ли номер версии Java во время выполнения заданный номер версии. Если он содержит, верните совпадение, в противном случае верните несоответствие |
@ConditionalOnProperty |
Требовать, чтобы свойства конфигурации соответствовали критериям |
@ConditionalOnJndi |
Местоположение должно существовать для данного jndi. В противном случае совпадение не возвращается. |
@ConditionalOnNotWebApplication |
Когда веб-среда не существует |
@ConditionalOnWebApplication |
Когда существует веб-среда |
@ConditionalOnResource |
Ресурсы, необходимые для развития, существуют |
III. Другое
0. Актуально
А. Больше сообщений в блоге
Основы
- 181009-Основное определение и использование компонентов в SpringBoot Basics
- 181012-SpringBoot Bean Основы автоматической загрузки
- 181013-Динамическая регистрация компонентов Springboot Basics
- 181018-SpringBoot Basics Условная инъекция Bean-компонента Положение использования @Condition
- 181019 — @ConditionalOnBean и @ConditionalOnClass компонентов SpringBoot Basics
- 181019-SpringBoot Basics Bean Условное внедрение @ConditionalOnProperty
- 181019-SpringBoot Basics Bean Условное внедрение @ConditionalOnExpression
Заявление
б. Исходный проект
- проект:spring-boot-demo
- module: 007-conditionbean
1. Серый блог
- One Grey BlogПерсональный блогblog.hhui.top
- Серый блог - специальный весенний блогspring.hhui.top
Серый личный блог, записывающий все посты блога по учебе и работе, приглашаю всех в гости
2. Заявление
Это не так хорошо, как письмо. Вышеупомянутое содержание чисто из семьи. Из-за ограниченных личных способностей неизбежно будут упущения и ошибки. Если вы обнаружите ошибки или у вас есть лучшие предложения, вы можете критиковать и поправьте их.
3. Сканируйте внимание
серый блог