Spring @Conditional xxx 相关注解介绍与使用

上文我们讲解了@Import的方式进行导入,本文我们将学习@Conditional xxx相关注解
主要有:

@Conditional 			   //   根据条件判断满足时,则实例化当前Bean
@ConditionalOnBean         //   当给定的在bean存在时,则实例化当前Bean
@ConditionalOnMissingBean  //   当给定的在bean不存在时,则实例化当前Bean
@ConditionalOnClass        //   当给定的类名在类路径上存在,则实例化当前Bean
@ConditionalOnMissingClass //   当给定的类名在类路径上不存在,则实例化当前Bean

一.@Conditional

public @interface Conditional {
    Class<? extends Condition>[] value();
}

根据源码我们使用此注解时,value的时需要继承Condition接口

假设:
bule这个Bean存在我们就实例化SuperMan
bule01这个Bean存在我们就实例化Man

这时我们就可以采用 @Conditional进行管理

1.1 定义相关类

@Data
public class SuperMan {
    private String name;
    private Integer age;
}
---------
@Data
public class Man {
    private String userName;
    private String email;
}
--------
@Data
public class Bule {
    private Integer code;
}

1.2 定义配置文件

1.2.1 定义Bean实例化文件
@Configuration
public class MainConfig {

    @Bean(value = "bule01")
    public Bule bule(){
        return new Bule();
    }

    @Bean
    @Conditional(value = SueperManCondition.class)
    public SuperMan superMan(){
        return new SuperMan("Javayh",27);
    }

    @Bean
    @Conditional(value = ManCondition.class)
    public Man man(){
        return new Man("Javayh","[email protected]");
    }
}
1.2.2 定义Bean实例化条件
public class ManCondition implements Condition  {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata annotatedTypeMetadata) {
        //获取到bean定义的注册类
        BeanDefinitionRegistry registry = context.getRegistry();
        //可以判断容器中的bean注册情况,也可以给容器中注册bean
        boolean definition = registry.containsBeanDefinition("bule01");
        if(definition){
            return true;
        }
        return false;
    }
}

--------
public class SueperManCondition implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata annotatedTypeMetadata) {
            //获取到bean定义的注册类
            BeanDefinitionRegistry registry = context.getRegistry();
            //可以判断容器中的bean注册情况,也可以给容器中注册bean
            boolean definition = registry.containsBeanDefinition("bule");
            if(definition){
                return true;
            }
        return false;
    }
}
1.2.3 验证
   AnnotationConfigApplicationContext applicationContext =
            new AnnotationConfigApplicationContext(MainConfig.class);

    @Test
    public void testCondtion(){
        printBeans(applicationContext);
        Bule bule = applicationContext.getBean(Bule.class);
        System.out.println(bule);
        SuperMan bean = applicationContext.getBean(SuperMan.class);
        System.out.println(bean);
        Man man = applicationContext.getBean(Man.class);
        System.out.println(man);
    }


    private void printBeans(AnnotationConfigApplicationContext applicationContext){
        String[] definitionNames = applicationContext.getBeanDefinitionNames();
        for (String name : definitionNames) {
            System.out.println(name);
        }
    }

运行之后我们发现,实例化bule01存在,这是根据条件将实例化man 这个Bean,而无法实例化 SuperMan
在这里插入图片描述

二.@ConditionalOnBean

源码可以看出,也用到了 @Conditional

@Conditional({OnBeanCondition.class})
public @interface ConditionalOnBean {
	//指定 条件的 Bean.Class
    Class<?>[] value() default {};
	//作为条件的类的Name,Class.getName()
    String[] type() default {};
	//条件所需的注解类
    Class<? extends Annotation>[] annotation() default {};
	//容器中bean的名字
    String[] name() default {};
	//搜索容器层级,当前容器,父容器
    SearchStrategy search() default SearchStrategy.ALL;
	//可能在其泛型参数中包含指定bean类型的其他类
    Class<?>[] parameterizedContainer() default {};
}

2.1 定义Bean

接下来我们修改上面的方放,当Bule作为SuperMan的变量

@Data
@AllArgsConstructor
public class SuperMan {
    private String name;
    private Integer age;
    private Bule bule;
}

2.2 定义Bean实例化规则

这是我们需要根据Bule是否在容器内,来进行SuperMan的实例化,做到Bule存在则SuperMan存在,否则不存在

@Configuration
public class MainConfig {

    @Bean(value = "bule")
    public Bule bule(){
        return new Bule();
    }

    @Bean
    @ConditionalOnBean(value = Bule.class)
    public SuperMan superMan(Bule bule){
        bule.setCode(123);
        return new SuperMan("Javayh",27,bule);
    }

    @Bean
    @Conditional(value = ManCondition.class)
    public Man man(){
        return new Man("Javayh","[email protected]");
    }
}

2.3 测试

    @Test
    public void testCondtionOnBean(){
        printBeans(applicationContext);
        SuperMan bean = applicationContext.getBean(SuperMan.class);
        System.out.println(bean);
    }

Bule存在容器中,SuperMan被实例化
在这里插入图片描述
这时我们可以将Bule的实例化注释掉,在进行测试,时容器内并没有Bule,而SuperMan也没 被实例化,我们书getBean就会错
在这里插入图片描述
@ConditionalOnMissingBean 其实与@ConditionalOnBean正好相反,这里就不做测试了

三.@ConditionalOnClass

public @interface ConditionalOnClass {
	//指定 条件的 Bean.Class
    Class<?>[] value() default {};
	//条件bean的名称
    String[] name() default {};
}

其实不难发现 ConditionalOnClass 和 ConditionalOnBean 左右是一样的,这是我们将 ConditionalOnBean 的例子改一下

    @Bean
    @ConditionalOnClass(value = Bule.class)
    public SuperMan superMan(Bule bule){
        bule.setCode(123);
        return new SuperMan("Javayh",27,bule);
    }

结果是一样
在这里插入图片描述
扩展
@ConditionalOnExpression(当表达式为true的时候,才会实例化一个Bean)
@ConditionalOnNotWebApplication(不是web应用)

本文的分享暂时就到这里,希望对您有所帮助
关注 Java有货领取更多资料

联系小编。微信:372787553,带您进群互相学习
左侧小编微信,右侧获取免费资料
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_38937840/article/details/104620277
今日推荐