SpringBoot(16)—@ConditionalOnBean與@ConditionalOnClass

@ConditionalOnBean與@ConditionalOnClass

上一篇講的@Conditional能夠經過條件控制是否注入Bean,這篇講下有關Bean其它幾個經常使用的註解使用方式java

@ConditionalOnBean         //   當給定的在bean存在時,則實例化當前Bean
@ConditionalOnMissingBean  //   當給定的在bean不存在時,則實例化當前Bean
@ConditionalOnClass        //   當給定的類名在類路徑上存在,則實例化當前Bean
@ConditionalOnMissingClass //   當給定的類名在類路徑上不存在,則實例化當前Bean

下面我經過案例深刻講下@ConditionalOnBean 註解,這個理解其它也就理解了。git

1、@ConditionalOnBean概念

需求場景 好比下面一種場景,我在實例化People對象的時候,須要注入一個City對象。這個時候問題來了,若是city沒有實例化,那麼下面就會報空指針或者直接報錯。
因此這裏需求很簡單,就是當前city存在則實例化people,若是不存在則不實例化people,這個時候@ConditionalOnBean 的做用來了。github

@Bean
    public People people(City city) {
        //這裏若是city實體沒有成功注入 這裏就會報空指針
        city.setCityName("千島湖");
        city.setCityCode(301701);
        return new People("小小", 3, city);
    }

一、@ConditionalOnBean註解定義

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnBeanCondition.class)
public @interface ConditionalOnBean {
    /**
     * 須要做爲條件的類的Class對象數組
     */
    Class<?>[] value() default {};
    /**
     * 須要做爲條件的類的Name,Class.getName()
     */
    String[] type() default {};
    /**
     *  (用指定註解修飾的bean)條件所需的註解類
     */
    Class<? extends Annotation>[] annotation() default {};
    /**
     * spring容器中bean的名字
     */
    String[] name() default {};
    /**
     * 搜索容器層級,當前容器,父容器
     */
    SearchStrategy search() default SearchStrategy.ALL;
    /**
     * 可能在其泛型參數中包含指定bean類型的其餘類
     */
    Class<?>[] parameterizedContainer() default {};
}

下面舉例說明。

spring

2、@ConditionalOnBean示例

一、Bean實體

1)City類數組

@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class City {
    /**
     * 城市名稱
     */
    private String cityName;
    /**
     * 城市code
     */
    private Integer cityCode;
}

2)People類測試

這裏City做爲People一個屬性字段。ui

@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class People {
  /**
     * 姓名
     */
    private String name;
    /**
     * 年齡
     */
    private Integer age;
    /**
     *  城市信息
     */
    private City city;
}

二、Config類

這裏寫個正常的配置類,City成功注入到IOC容器中。指針

@Slf4j
@Configuration
public class Config {
    @Bean
    public City city() {
        City city = new City();
        city.setCityName("千島湖");
        return city;
    }
    @Bean
    public People people(City city) {
        //這裏若是city實體沒有成功注入 這裏就會報空指針
        city.setCityCode(301701);
        return new People("小小", 3, city);
    }
}

三、Test測試類

@SpringBootTest(classes = Application.class)
@RunWith(SpringRunner.class)
public class TestConditionOn {

    @Autowired(required=false)
    private People people;
    
    @Test
    public void test() {
        System.out.println("= = = = = = = = = = = = = ");
        System.out.println("people = " + people);
        System.out.println("= = = = = = = = = = = = = ");
    }
}

運行結果code

一切正常,這個很符合咱們實際開發中的需求。可是若是有一種狀況,就是個人city並無被注入。我把上面這部分注視掉。對象

//    @Bean
//    public City city() {
//        City city = new City();
//        city.setCityName("千島湖");
//        return city;
//    }

再運行測試類

發現啓動直接報錯了,這固然不是咱們但願看到的,咱們是要當city已經注入那麼實例化people,若是沒有注入那麼不實例化people。

@Slf4j
@Configuration
public class Config {
//    @Bean
//    public City city() {
//        City city = new City();
//        city.setCityName("千島湖");
//        return city;
//    }

    /**
     * 這裏加了ConditionalOnBean註解,就表明若是city存在才實例化people
     */
    @Bean
    @ConditionalOnBean(name = "city")
    public People people(City city) {
        //這裏若是city實體沒有成功注入 這裏就會報空指針
        city.setCityCode(301701);
        return new People("小小", 3, city);
    }
}

再運行測試類

很明顯,上面由於city已經註釋調,因此也致使沒法實例化people,因此people爲null。

注意有點要注意的,就是一旦使用@Autowired那就默認表明當前Bean必定是已經存在的,若是爲null,會報錯。因此這裏要修改下。

@Autowired(required=false) //required=false 的意思就是容許當前的Bean對象爲null。

總結講了這個註解,其它三個註解的意思大體差很少,在實際開發過程當中能夠根據實際狀況使用該註解。
GitHub源碼 https://github.com/yudiandemingzi/SpringBootBlog
項目名稱 04-conditionalon




只要本身變優秀了,其餘的事情纔會跟着好起來(中將4)
相關文章
相關標籤/搜索