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,帶您進羣互相學習
左側小編微信,右側獲取免費資料
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章