背景:
就是这个注解 @Conditional,当时看 springboot 源码的时候,看到很多次。btw,后续如果有时间和精力的话,还会结合 springboot 源码进一步体会这个注解的使用。
实验:
-
@Conditional 注解 :根据一定条件进行判断,满足条件才会注入相应的 bean;不满足条件则不会注入bean。通过查看这个注解的源代码,如下所示:
首先,该注解可以标注在类或者方法上;
其次,该注解的 value 属性为实现了 Condition 接口的子类。 -
因此,自定义一个实现了 Condition 接口的子类 XxxCondition,重写 matches() 方法。该方法的返回值 true/false 决定了组件是否注入到 IOC 容器中。
public class XxxCondition implements Condition {
/*
* context: 上下文环境,可以从中获取很多东西
* metaData: 注释信息
*/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// 获取bean定义的注册类
BeanDefinitionRegistry registry = context.getRegistry();
// 获取类加载器
ClassLoader classLoader = context.getClassLoader();
// 获取beanFactory
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
// ...
// 获取当前环境信息。
ConfigurableEnvironment environment = (ConfigurableEnvironment) context.getEnvironment();
String osName = environment.getProperty("os.name"); // Windows 10
if(osName.equals("Windows 10")){
return true;
}
return false;
}
}
- 在配置类中,通过@Conditional 注解“选择性”地注入 Person 组件。而且,我是把这个注解先加在了方法上。后面可以改在类上,测试下具体效果(标注在类上的话,效果为:若@Conditional 注解的条件满足,则该配置类中全部组件的注入才会生效;否则,均不生效)。
@Conditional(value={XxxCondition.class})
@Bean
public Person person(){
return new Person("Taylor", 29);
}
上面代码的含义是:若当前环境为 Windows 10 操作系统,则注入 name 为 Taylor 的 Person 组件;若不是,则不会注入。
我是通过运行时的环境变量 os.name 来进行判断的,而我的电脑就是 win10 操作系统,所以能够从容器中获取到该组件。如果你的电脑是其它系统,还可以指定运行时参数:-Dos.name=xxx (-D 是固定写法)。
顺便说一下,后面将要介绍的 @PropertySource 注解就是将配置文件中的信息加载到了内存中,所以我们可以从当前环境中获取相应内容:
ConfigurableEnvironment environment = (ConfigurableEnvironment) context.getEnvironment();
String value= environment.getProperty("字段key");