@ConditionalOnMissingBean與@ConditionalOnBean
倆個(gè)作用:根據(jù)當(dāng)前環(huán)境或者容器情況來(lái)動(dòng)態(tài)注入bean纳像,要配合@Bean使用
@ConditionalOnMissingBean作用:判斷當(dāng)前需要注入Spring容器中的bean的實(shí)現(xiàn)類(lèi)是否已經(jīng)含有婴栽,有的話不注入帆竹,沒(méi)有就注入
@ConditionalOnBean作用:判斷當(dāng)前需要注冊(cè)的bean的實(shí)現(xiàn)類(lèi)否被spring管理合砂,如果被管理則注入目胡,反之不注入
@ConditionalOnMissingBean锯七,它是修飾bean的一個(gè)注解,主要實(shí)現(xiàn)的是誉己,當(dāng)你的bean被注冊(cè)之后眉尸,如果而注冊(cè)相同類(lèi)型的bean,就不會(huì)成功巨双,它會(huì)保證你的bean只有一個(gè)噪猾,即你的實(shí)例只有一個(gè),當(dāng)你注冊(cè)多個(gè)相同的bean時(shí)筑累,會(huì)出現(xiàn)異常袱蜡,以此來(lái)告訴開(kāi)發(fā)人員。
@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);
}
}
因?yàn)樵赼Mapper1上面標(biāo)識(shí)了AMapper類(lèi)型的bean只能有一個(gè)實(shí)現(xiàn) @ConditionalOnMissingBean(AMapper.class)疼阔,所以在進(jìn)行aMapper2注冊(cè)時(shí)戒劫,系統(tǒng)會(huì)出現(xiàn)上面圖上的異常半夷,這是正常的。
當(dāng)我們把 @ConditionalOnMissingBean(AMapper.class) 去掉之后迅细,你的bean可以注冊(cè)多次巫橄,這時(shí)需要用的@Primary來(lái)確定你要哪個(gè)實(shí)現(xiàn);一般來(lái)說(shuō)茵典,對(duì)于自定義的配置類(lèi)湘换,我們應(yīng)該加上@ConditionalOnMissingBean注解,以避免多個(gè)配置同時(shí)注入的風(fēng)險(xiǎn)统阿。
@Primary標(biāo)識(shí)哪個(gè)是默認(rèn)的bean
@Bean
public AMapper aMapper1(AConfig aConfig) {
return new AMapperImpl1(aConfig);
}
@Bean
@Primary
public AMapper aMapper2(AConfig aConfig) {
return new AMapperImpl2(aConfig);
}
另一個(gè)案例
程序入口: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及其實(shí)現(xiàn)類(lèi):
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:吾乃新日暮里的王,三界哲學(xué)的主宰扶平。");
}
}
VanConfig:
@Configuration
public class VanConfig {
@Bean
@ConditionalOnBean(Billy.class)
public Fighter fighter(){
return new Billy();
}
@Bean
@ConditionalOnMissingBean
public Fighter fighter2(){
return new Babana();
}
}
1帆离、運(yùn)行程序,輸入結(jié)果如下:
Billy:吾乃新日暮里的王结澄,三界哲學(xué)的主宰哥谷。
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();
}
}
重新運(yùn)行麻献,輸入結(jié)果如下:
Banana: 自由的氣息们妥,蕉遲但到
3、或者勉吻,我們將Billy上的@Service注解注釋掉监婶,讓springboot掃描不到該類(lèi):
//@Service
public class Billy implements Fighter {
public void fight(){
System.out.println("Billy:吾乃新日暮里的王,三界哲學(xué)的主宰齿桃。");
}
}
同時(shí)恢復(fù)VanConfig里的配置:
@Configuration
public class VanConfig {
@Bean
@ConditionalOnBean(Billy.class)
public Fighter fighter(){
return new Billy();
}
@Bean
@ConditionalOnMissingBean
public Fighter fighter2(){
return new Babana();
}
}
再次運(yùn)行惑惶,輸入結(jié)果如下(與第2次試驗(yàn)的效果相同):
場(chǎng)景實(shí)例:
Service 層,通過(guò)@ConditionalOnProperty 判斷,然后結(jié)合@ConditionalOnMissingBean(xx.class) 做只能生效一個(gè)service