1. Что такое аннотация @Conditional
@Conditional
Это следует изspring-context
комментария под пакетом.- Настройте некоторые условные суждения через @Conditional.Когда все условия будут выполнены, цель, отмеченная аннотацией @Conditional, будет обработана Spring.
-
Например, в соответствии с текущей средой, системными свойствами, файлами конфигурации и другими условиями, чтобы решить, регистрировать ли Bean-компонент или выполнять определенный компонент.
-
Сценарий приложения
- В определенной среде необходимо зарегистрировать определенный компонент, который обычно используется для регистрации, когда компонент не существует.
- В соответствии со свойством в файле конфигурации решить, следует ли регистрировать bean-компонент.
- Выберите класс конфигурации в соответствии со средой, такой как тип операционной системы и версия текущей системы, чтобы определить, следует ли его выполнять.
2. Анализ исходного кода аннотации @Conditional
- По его аннотациям можно узнать, что он чисто функциональная аннотация, он не зависит от других аннотаций, а на класс всего три метааннотации .
@Target({
ElementType.TYPE, ElementType.METHOD}) //注解作用范围在接口、类、枚举、注解、方法
@Retention(RetentionPolicy.RUNTIME) //保留到运行期,jvm加载class文件之后,仍然存在
@Documented //生成javadoc文档
public @interface Conditional {
/**
* All {@link Condition} classes that must {@linkplain Condition#matches match}
* in order for the component to be registered.
*/
Class<? extends Condition>[] value();
}
- значение: массив типа Condition, Condition — это интерфейс, представляющий условное суждение, и внутри есть метод для возврата true или false
- Когда все условия условия истинны, результат @Conditional истинен
Вопрос: Так что же это за состояние?
-
Условие само по себе является интерфейсом.Метод match в исходном коде оценивает, соответствует ли условие.В методе есть два параметра:
-
context context, получить информацию о компоненте в контейнере
-
метаданные: получить всю аннотационную информацию об объекте, отмеченном @Conditional
public interface Condition { //判断条件是否匹配 boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata); }
-
-
Давайте посмотрим на исходный код ConditionContext.
public interface ConditionContext {
//返回bean定义注册器,用于获取Bean定义的注册表,可以用来注册和获取bean定义的各种配置信息
BeanDefinitionRegistry getRegistry();
//用于获取Bean工厂,可以用来获取或操作Bean实例,相当于一个ioc容器对象
ConfigurableListableBeanFactory getBeanFactory();
//用于获取环境变量和属性值等配置信息
Environment getEnvironment();
//用于获取资源文件,比如XML文件、图片、文本等
ResourceLoader getResourceLoader();
//用于获取类加载器,可以用来加载类或资源文件
ClassLoader getClassLoader();
}
-
Главное здесь — BeanDefinitionRegistry, который возвращает регистр определения бина, который используется для получения реестра определения бина, которым мы воспользуемся позже.
-
Исходный код BeanDefinitionRegistry
public interface BeanDefinitionRegistry extends AliasRegistry {
//用于向Bean定义注册表中注册一个Bean定义,参数beanName表示Bean的名称,beanDefinition表示Bean的定义信息
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition);
//从Bean定义注册表中移除指定名称的Bean定义,参数beanName表示要移除的Bean名称
void removeBeanDefinition(String beanName) ;
//获取指定名称的Bean定义,参数beanName表示要获取的Bean名称
BeanDefinition getBeanDefinition(String beanName) ;
//判断指定名称的Bean定义是否存在于注册表中,参数beanName表示要判断的Bean名称
boolean containsBeanDefinition(String beanName);
//获取所有Bean定义的名称,返回一个String数组
String[] getBeanDefinitionNames();
//获取Bean定义的数量。
int getBeanDefinitionCount();
//判断指定名称的Bean是否已经被使用,参数beanName表示要判断的Bean名称。如果该名称已经被使用,则返回true,否则返回false
boolean isBeanNameInUse(String beanName);
}
- Введение в BeanDefinitions
- BeanDefinition — одна из наиболее важных концепций в контейнере Spring, которая является основой контейнера для создания и управления экземплярами Bean, абстрагирования и инкапсуляции информации об определениях Bean.
- Описать информацию об определении компонента, включая имя компонента, тип, область действия, атрибуты и другую информацию.
- Создание и управление бинами можно настроить и контролировать в деталях, например, указать область действия бина, указать, загружается ли он отложенно, внедряется ли он автоматически, и другие атрибуты.
- Назначение BeanDefinition
- Определите основную информацию о Bean-компоненте, включая имя, тип и область действия Bean-компонента.
- Определить информацию об атрибутах Bean, включая имя, тип, значение атрибута Bean и т. д.
- Определите информацию о жизненном цикле Bean-компонента, включая метод инициализации и метод уничтожения Bean-компонента.
- Определите зависимости, такие как bean-компоненты, включая зависимости между bean-компонентами, методы внедрения и т. д.
- Определить Bean и другую информацию AOP, включая аспекты, уведомления, pointcut и т. д.
3. @Conditional аннотация в случае реального боя
-
Предыстория требования: теперь в системе есть два набора источников данных, имитирующих баскетбольную мобилизацию, один официальный, а другой запасной.Только когда официальный не может играть, запасной будет играть.
-
Кодирование в действии
Создайте объектный компонент баскетболиста
@Data @AllArgsConstructor @NoArgsConstructor public class BasketballPlayers { /** * 姓名 */ private String name; /** * 年龄 */ private int age; /** * 性别 */ private String sex; }
Создайте класс конфигурации компонента
public class BasketballPlayersConfig { @Bean("lixiang") public BasketballPlayers BasketballPlayers1(){ return new BasketballPlayers("李祥",18,"男"); } @Bean("zhangsan") public BasketballPlayers BasketballPlayers2(){ return new BasketballPlayers("张三",18,"男"); } }
Пользовательский класс условий
public class MyCondition implements Condition { @Override public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { BeanDefinitionRegistry registry = conditionContext.getRegistry(); //不存在,才返回true boolean flag = !registry.containsBeanDefinition("lixiang"); return flag; } }
тестовый код
public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); //扫描指定的包,包括子包 context.scan("com.lixiang"); //里面完成初始化操作,核心方法 context.refresh(); Map<String, BasketballPlayers> beansOfType = context.getBeansOfType(BasketballPlayers.class); System.out.println(beansOfType); }