@Conditional 是spring4.0中引入的的,不是springBoot特有的,只不过在springBoot中做了优化,不要被文章的标题所误导!
我们都知道springBoot之所以可以实现快速开发是因为它有自动配置,而实现自动化配置的核心就是@Conditional。而@Conditional在日常开发中不经常使用,但是它的地位是举足轻重的。
@Conditional顾名思义,就是条件注解,根据满足某一个特定的条件创建一个特定的Bean
源码如下:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
/**
* All {@link Condition}s that must {@linkplain Condition#matches match}
* in order for the component to be registered.
*/
Class<? extends Condition>[] value();
}
@FunctionalInterface
public interface Condition {
/**
* Determine if the condition matches.
* @param context the condition context
* @param metadata metadata of the {@link org.springframework.core.type.AnnotationMetadata class}
* or {@link org.springframework.core.type.MethodMetadata method} being checked
* @return {@code true} if the condition matches and the component can be registered,
* or {@code false} to veto the annotated component's registration
*/
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
Condition是一个接口,实现这个接口重写matches 方法,其返回值是一个boolean 类型,从而决定是否需要加载Bean,当为true时满足条件,为false时不满足条件!
案例说明:根据开发人员会的技能让其做相应的开发!
- 定义一个技能接口,里面有一个技能类型的方法
public interface Skills {
public String skillType();
}
2.定义 Java技能
public class JavaSkill implements Skills {
@Override
public String skillType() {
// TODO Auto-generated method stub
return "做java开发!";
}
}
3.定义 Python技能
public class PythonSkill implements Skills {
@Override
public String skillType() {
// TODO Auto-generated method stub
return "做Python开发!";
}
}
- 定义 JavaSkillCondition 用于条件判断
public class JavaSkillCondition implements Condition{
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// 做其他判断
return true;
}
}
- 定义 PythonSkillCondition 用于条件判断
public class PythonSkillCondition implements Condition{
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// 做其他判断
return false;
}
}
- 定义 SkillConfig 满足相应技能 注入相应Bean
@Configuration
public class SkillConfig {
@Bean("Skills")
@Conditional(JavaSkillCondition.class)
public Skills getJavaSkill() {
return new JavaSkill();
}
@Bean("Skills")
@Conditional(PythonSkillCondition.class)
public Skills getPythonSkill() {
return new PythonSkill();
}
}
定义了一个技能接口 Skills,接口中有一个方法 skillType,两个实现类(JavaSkill和PythonSkill)实现这个接口,接着定义了满足注入JavaSkill 的条件JavaSkillCondition和满足注入PythonSkill的条件PythonSkillCondition,最后配置了一个configuration来实现配置Bean。值得注意的是:
1. 两个 Bean 的名字都为Skills ,因为两个Bean的返回值都是起父类对象Skills ,当然可以修改成任意的值,但要和获取的getBean的参数保持一致。
2. 每个 Bean 上都有一个 @Conditional 注解,当 @Conditional 注解中配置的条件类的 matches 方法返回值为 true 时,对应的 Bean 就会生效!
测试:
@SpringBootApplication
public class AppNettyClient {
public static void main(String[] args) {
ConfigurableApplicationContext application= SpringApplication.run(AppNettyClient.class, args);
Skills skills = (Skills)application.getBean("Skills");
System.out.println(skills.skillType());
}
}
再次切换matches 方法返回值进行测试,控制台会输出不同的结果!