Java专题

springboot @ConditionalOnMissing

2020-11-14  本文已影响0人  zhuchunyan_aiji

@ConditionalOnMissingBean与@ConditionalOnBean

俩个作用:根据当前环境或者容器情况来动态注入bean,要配合@Bean使用
@ConditionalOnMissingBean作用:判断当前需要注入Spring容器中的bean的实现类是否已经含有,有的话不注入,没有就注入
@ConditionalOnBean作用:判断当前需要注册的bean的实现类否被spring管理,如果被管理则注入,反之不注入

@ConditionalOnMissingBean,它是修饰bean的一个注解,主要实现的是,当你的bean被注册之后,如果而注册相同类型的bean,就不会成功,它会保证你的bean只有一个,即你的实例只有一个,当你注册多个相同的bean时,会出现异常,以此来告诉开发人员。

@Component
public class AutoConfig {
  @Bean
  public AConfig aConfig() {
    return new AConfig("lind");
  }

  @Bean
  @ConditionalOnMissingBean(AMapper.class)
  public AMapper aMapper1(AConfig aConfig) {
    return new AMapperImpl1(aConfig);
  }

  @Bean
  public AMapper aMapper2(AConfig aConfig) {
    return new AMapperImpl2(aConfig);
  }
}

因为在aMapper1上面标识了AMapper类型的bean只能有一个实现 @ConditionalOnMissingBean(AMapper.class),所以在进行aMapper2注册时,系统会出现上面图上的异常,这是正常的。

当我们把 @ConditionalOnMissingBean(AMapper.class) 去掉之后,你的bean可以注册多次,这时需要用的@Primary来确定你要哪个实现;一般来说,对于自定义的配置类,我们应该加上@ConditionalOnMissingBean注解,以避免多个配置同时注入的风险。

@Primary标识哪个是默认的bean

@Bean
  public AMapper aMapper1(AConfig aConfig) {
    return new AMapperImpl1(aConfig);
  }

  @Bean
  @Primary
  public AMapper aMapper2(AConfig aConfig) {
    return new AMapperImpl2(aConfig);
  }

另一个案例
程序入口:ConditionalDemoApplication:

@SpringBootApplication
public class ConditionalDemoApplication implements CommandLineRunner {
    @Autowired
    private Van van;

    public static void main(String[] args) {
        SpringApplication.run(ConditionalDemoApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception{
        van.fight();
    }
}

Van.java

@Service
public class Van {
    @Autowired
    private Fighter fighter;

    public void fight(){
        System.out.println("van:boy next door,do you like 玩游戏");
        fighter.fight();
    }
}

Fighter.java及其实现类:

public interface Fighter {
    void fight();
}
@Service
public class Babana implements Fighter {
    @Override
    public void fight(){
        System.out.println("Banana: 自由的气息,蕉迟但到");
    }
}
@Service
public class Billy implements Fighter {
    public void fight(){
        System.out.println("Billy:吾乃新日暮里的王,三界哲学的主宰。");

    }
}

VanConfig:

@Configuration
public class VanConfig {
    @Bean
    @ConditionalOnBean(Billy.class)
    public Fighter fighter(){
        return new Billy();
    }

    @Bean
    @ConditionalOnMissingBean
    public Fighter fighter2(){
        return new Babana();
    }
}

1、运行程序,输入结果如下:
Billy:吾乃新日暮里的王,三界哲学的主宰。

2、如果将Billy Bean的代码注释掉:

@Configuration
public class VanConfig {
    /*@Bean
    @ConditionalOnBean(Billy.class)
    public Fighter fighter(){
        return new Billy();
    }*/

    @Bean
    @ConditionalOnMissingBean
    public Fighter fighter2(){
        return new Babana();
    }
}

重新运行,输入结果如下:
Banana: 自由的气息,蕉迟但到

3、或者,我们将Billy上的@Service注解注释掉,让springboot扫描不到该类:

//@Service
public class Billy implements Fighter {
    public void fight(){
        System.out.println("Billy:吾乃新日暮里的王,三界哲学的主宰。");

    }
}
同时恢复VanConfig里的配置:
@Configuration
public class VanConfig {
    @Bean
    @ConditionalOnBean(Billy.class)
    public Fighter fighter(){
        return new Billy();
    }

    @Bean
    @ConditionalOnMissingBean
    public Fighter fighter2(){
        return new Babana();
    }
}
再次运行,输入结果如下(与第2次试验的效果相同):

场景实例:
Service 层,通过@ConditionalOnProperty 判断,然后结合@ConditionalOnMissingBean(xx.class) 做只能生效一个service

上一篇下一篇

猜你喜欢

热点阅读