上一篇讲的@Conditional可以通过条件控制是否注入Bean,这篇讲下有关Bean其它几个常用的注解使用方式
@ConditionalOnBean // 当给定的在bean存在时,则实例化当前Bean @ConditionalOnMissingBean // 当给定的在bean不存在时,则实例化当前Bean @ConditionalOnClass // 当给定的类名在类路径上存在,则实例化当前Bean @ConditionalOnMissingClass // 当给定的类名在类路径上不存在,则实例化当前Bean
下面我通过案例深入讲下@ConditionalOnBean 注解,这个理解其它也就理解了。
需求场景 比如下面一种场景,我在实例化People对象的时候,需要注入一个City对象。这个时候问题来了,如果city没有实例化,那么下面就会报空指针或者直接报错。
 所以这里需求很简单,就是当前city存在则实例化people,如果不存在则不实例化people,这个时候@ConditionalOnBean 的作用来了。
    @Bean     public People people(City city) {         //这里如果city实体没有成功注入 这里就会报空指针         city.setCityName("千岛湖");         city.setCityCode(301701);         return new People("小小", 3, city);     }  @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 {}; } 下面举例说明。
1)City类
@Data @ToString @AllArgsConstructor @NoArgsConstructor public class City {     /**      * 城市名称      */     private String cityName;     /**      * 城市code      */     private Integer cityCode; } 2)People类
这里City作为People一个属性字段。
@Data @ToString @NoArgsConstructor @AllArgsConstructor public class People {   /**      * 姓名      */     private String name;     /**      * 年龄      */     private Integer age;     /**      *  城市信息      */     private City city; }  这里写个正常的配置类,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);     } }  @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("= = = = = = = = = = = = = ");     } } 运行结果

一切正常,这个很符合我们实际开发中的需求。但是如果有一种情况,就是我的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)