持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情
1. @Conditional 条件注解
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
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();
}
@Conditional 不仅可以作用到类上,也可以使用到方法上
注解中存在 Condition 类
@FunctionalInterface
public interface Condition {
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
使用 @Conditional 注解,需要写一个类来实现 spring 提供的 Condition 接口,会使用 matches 方法去匹配
2. 带条件向容器中注册 bean, 使用 @Conditional
例如,依据当前操作系统类型注入不同类型的bean;如windows下注入名称为 bill 的 Person;如 linux 下注入名称为linus 的Person对象;
获取操作系统的类型
LinuxCondition 类型
public class LinuxCondition implements Condition {
/**
* 方法匹配
* ConditionContext 判断条件上下文
*
* @param context
* @param metadata
* @return
*/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
ClassLoader classLoader = context.getClassLoader();
// 获取到 bean 注册的定义类
BeanDefinitionRegistry registry = context.getRegistry();
// 获取当前系统环境变量
Environment environment = context.getEnvironment();
// 里面含有 os.name 的属性
String property = environment.getProperty("os.name");
if (property.contains("linux")) {
return true;
}
return false;
}
}
public class WindowsConditional implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment environment = context.getEnvironment();
String property = environment.getProperty("os.name");
if (property.contains("Windows")) {
return true;
}
return false;
}
}
MainBeanConfig2 配置文件
@Configuration
public class MainBeanConfig2 {
// 按照条件:如果是 windows系统,则注入bill bean
@Conditional(WindowsConditional.class)
@Bean("bill")
public Person person01() {
return new Person("bill", 1);
}
// 按照条件:如果是 linux 系统,则注入linus bean
@Conditional(LinuxCondition.class)
@Bean("linus")
public Person person02() {
return new Person("linus", 2);
}
}
执行test测试
@Test
public void testBean05() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainBeanConfig2.class);
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String bean : beanDefinitionNames) {
System.out.println("bean = " + bean);
}
}
idea 中设置操作系统的参数: vm option :-Dos.name=linux
设置运行参数,可以通过 environment.getProperty("os.name") 获取当前spring容器运行的操作环境
结果显示 linus
但是,现在去掉 vm options 参数;
结果显示 bill
3. @Condtional 扩展
再 springboot 中 @Conditional 注解用的特别多,类似的还有,还挺重要的
- @ConditionalOnBean 当容器中存在某个bean的时候,此注解才会生效
- @ConditionalOnMissingBean 与上面相反,当容器中缺少某个 bean 的时候,注解才会生效
- @ConditionalOnClass 当前上下文容器中有某个类的时候,注解生效,配置开启
- @ConditionalOnMissingClass 与上面相反,容器中不存在某个类的时候,注解生效