1. 业务背景
2. @ConditionalOnProperty的作用
在Spring Boot的自动配置中经常看到@ConditionalOnProperty注解的使用,这个注解就是控制在指定的条件下,是否需要加载这个bean。
3. @ConditionalOnProperty属性说明
RetentionPolicy.RUNTIME) (ElementType.TYPE, ElementType.METHOD }) ({ OnPropertyCondition.class) (public@interfaceConditionalOnProperty { // 数组,获取对应property名称的值,与name不可同时使用String[] value() default {}; // 配置属性名称的前缀,比如spring.httpStringprefix() default""; // 数组,配置属性完整名称或部分名称// 可与prefix组合使用,组成完整的配置属性名称,与value不可同时使用String[] name() default {}; // 获取配置文件中key为name属性的值,比较该值与havingValue给定的值是否相同,相同才加载配置StringhavingValue() default""; // 如果为true,没有该配置属性时也会正常加载;反之则不会生效,表示配置文件中如果没有name属性配置的keybooleanmatchIfMissing() defaultfalse;
4. @ConditionalOnProperty使用范围
ElementType.TYPE, ElementType.METHOD }) ({
注解的@Target属性值为TYPE、METHOD,就表示当前注解在类和方法上都可以使用。
5. @ConditionalOnProperty使用方式
直接在@Configuration、@Bean上同级进行使用,如果满足条件就表示可以加载该类,如果不满足条件就不加载这个bean到Spring容器中。
在配置文件中配置好yunqiao.dingtalk.env参数
yunqiao.dingtalk.env: ${DINGTALK_ENV:private} #配置走公有钉或专有钉逻辑
在共有钉逻辑中设置@ConditionalOnProperty的havingValue = "public"
value="yunqiao.dingtalk.env", havingValue="public") (publicclassDingTalkLoginServiceImplimplementsDingTalkLoginService { ... }
在私有钉逻辑中设置@ConditionalOnProperty的havingValue = "private"
value="yunqiao.dingtalk.env", havingValue="private") (publicclassPrivateDingTalkLoginServiceImplimplementsDingTalkLoginService { ... }
如果在配置中设置为共有钉逻辑“public”,则走DingTalkLoginServiceImpl方法,若在配置中设置为私有钉逻辑“private”,则走PrivateDingTalkLoginServiceImpl方法。
6. @Conditional相关注解
RetentionPolicy.RUNTIME) (ElementType.TYPE, ElementType.METHOD}) ({OnPropertyCondition.class}) ({
- 都可以应用在 TYPE 上,也就是说,Spring 自动扫描的一切类 (@Configuration, @Component, @Service, @Repository, or @Controller) 都可以通过添加相应的 @ConditionalOnXxxx 来判断是否加载
- 都可以应用在 METHOD 上,所以有 @Bean 标记的方法也可以应用这些注解
- 都是用了 @Conditional 注解来标记,OnBeanCondition 等自定义 Condition 还是实现了 Condition 接口的
7. 总结
我们可以通过@ConditionalOnProperty等注解控制不同条件下走哪条逻辑,从而在指定的条件下,灵活的配置是否需要加载某些配置,将配置和硬编码进行解耦,提高灵活性和扩展性。