文章目录
前言
@ConditionalOnProperty 是Spring Boot中的条件注解,它的核心功能是通过属性名以及属性值来实现的,常被用于判断某个属性是否存在,然后决定某个Bean是否创建;
一、使用场景
一般用于是否要创建,或者注入到spring中的bean的条件判断,例如: spring中一定有对于mysql的一些默认配置,但是当我不引入mysql,yml中不做配置的时候,这些类是不会被注入的,当我在yml中引入mysql的相关配置,那么相应的数据源,mysql等相关bean就会被注入其中;
二、使用步骤
这里举个例子,也是项目中常见的问题,当一个实现类有两个实现类的时候,我们注入使用的时候会有问题;
1.错误示例
- 一个接口
java
public interface TestConditionOnProperty {
void sout();
}
-
两个实现类
@Service
public class TestConditionOnProperty1 implements TestConditionOnProperty {
@Override
public void sout() {
System.out.println(">>>>>>>>>>>>>> TestConditionOnProperty1 <<<<<<<<<<<<");
}
}@Service
public class TestConditionOnProperty2 implements TestConditionOnProperty {
@Override
public void sout() {
System.out.println(">>>>>>>>>>>>>> TestConditionOnProperty2 <<<<<<<<<<<<");
}
} -
开始测试, 问题出现
@SpringBootTest
class TestConditionOnPropertyTest {@Autowired TestConditionOnProperty testConditionOnProperty; @Test void sout() { testConditionOnProperty.sout(); }
}
TestConditionOnProperty 应该是唯一的,但是找到了两个:
expected single matching bean but found 2: testConditionOnProperty1,testConditionOnProperty2
-
解决方案: 加上@Qualifier ,指定其中一个具体实现类
@SpringBootTest
class TestConditionOnPropertyTest {@Qualifier("testConditionOnProperty1") @Autowired TestConditionOnProperty testConditionOnProperty; @Test void sout() { testConditionOnProperty.sout(); }
}
2.@ConditionalOnProperty的解决方案
- 依然是如上代码,但是改造下,TestConditionOnProperty1 和 TestConditionOnProperty2 各增加一行代码
java
@Service
@ConditionalOnProperty(name = "TestConditionOnProperty",havingValue = "TestConditionOnProperty1")
public class TestConditionOnProperty1 implements TestConditionOnProperty {
@Override
public void sout() {
System.out.println(">>>>>>>>>>>>>> TestConditionOnProperty1 <<<<<<<<<<<<");
}
}
@Service
@ConditionalOnProperty(name = "TestConditionOnProperty",havingValue = "TestConditionOnProperty2")
public class TestConditionOnProperty2 implements TestConditionOnProperty {
@Override
public void sout() {
System.out.println(">>>>>>>>>>>>> TestConditionOnProperty2 <<<<<<<<<<<<<<");
}
}
-
yml增加配置
TestConditionOnProperty: TestConditionOnProperty2
@ConditionalOnProperty(name = "TestConditionOnProperty",havingValue = "TestConditionOnProperty2")其中
name 与yml配置中的 TestConditionOnProperty对应
对应后,会读取到值为TestConditionOnProperty2, 与当前注解中的havingValue 值比对
结果为true生效,注入当前bean,结果为true失效,不注入当前bean
最终其实就是只注入了一个bean
-
再次测试
@SpringBootTest
class TestConditionOnPropertyTest {@Autowired TestConditionOnProperty testConditionOnProperty; @Test void sout() { testConditionOnProperty.sout(); }
}
总结
其实这个注解 @ConditionalOnProperty 相当于就是java SPI机制的另一种实现方式,更加灵活,在配置文件中更改,当注册中心为nacos,可以实现不重启项目就能自如切换相应实现类的效果;
也就是热加载的效果,热加载其实是 @RefreshScope 发生的了作用 @RefreshScope概述