Spring Boot中@ConditionalOnProperty使用详解
在 Spring Boot 的自动配置中经常看到 @ConditionalOnProperty 注解的使用,本篇文章带大家来了解一下该注解的功能。
Spring Boot 中的使用
在 Spring Boot 的源码中,比如涉及到 Http 编码的自动配置、数据源类型的自动配置等大量的使用到了 @ConditionalOnProperty 的注解。
HttpEncodingAutoConfiguration 类中部分源代码:
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(HttpProperties.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass(CharacterEncodingFilter.class)
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {
// 省略内部代码
}
DataSourceConfiguration 类中部分代码:
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(org.apache.tomcat.jdbc.pool.DataSource.class)
@ConditionalOnMissingBean(DataSource.class)
@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "org.apache.tomcat.jdbc.pool.DataSource",
matchIfMissing = true)
static class Tomcat {
// 省略内部代码
}
很显然,以上两个自动配置类中都通过 @ConditionalOnProperty 来控制自动配置是否生效,下面我们来了解一下它的源码和具体使用。
@ConditionalOnProperty 源码说明
@ConditionalOnProperty 注解类源码如下:
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnPropertyCondition.class)
public @interface ConditionalOnProperty {
<span class="hljs-comment">// 数组,获取对应property名称的值,与name不可同时使用</span>
String<span class="hljs-selector-attr">[]</span> <span class="hljs-built_in">value</span>() default {};
<span class="hljs-comment">// 配置属性名称的前缀,比如spring.http.encoding</span>
String <span class="hljs-built_in">prefix</span>() default "";
<span class="hljs-comment">// 数组,配置属性完整名称或部分名称</span>
<span class="hljs-comment">// 可与prefix组合使用,组成完整的配置属性名称,与value不可同时使用</span>
String<span class="hljs-selector-attr">[]</span> <span class="hljs-built_in">name</span>() default {};
<span class="hljs-comment">// 可与name组合使用,比较获取到的属性值与havingValue给定的值是否相同,相同才加载配置</span>
String <span class="hljs-built_in">havingValue</span>() default "";
<span class="hljs-comment">// 缺少该配置属性时是否可以加载。如果为true,没有该配置属性时也会正常加载;反之则不会生效</span>
boolean <span class="hljs-built_in">matchIfMissing</span>() default false;
}
其中在历史版本中还存在一个 relaxedNames 属性:
// 是否可以松散匹配
boolean relaxedNames() default true;
最新版本中已经不存在该属性了。
通过注解 ConditionalOnProperty 上的 @Conditional(OnPropertyCondition.class) 代码,可以看出 ConditionalOnProperty 属于 @Conditional 的衍生注解。生效条件由 OnPropertyCondition 来进行判断。
使用方法
关于 @ConditionalOnProperty 的使用方法,我们在上面的 Spring Boot 中的使用已经看到。
@ConditionalOnProperty 的核心功能是通过属性 name 以及 havingValue 来实现的。
首先看 matchIfMissing 属性,用来指定如果配置文件中未进行对应属性配置时的默认处理:默认情况下 matchIfMissing 为 false,也就是说如果未进行属性配置,则自动配置不生效。如果 matchIfMissing 为 true,则表示如果没有对应的属性配置,则自动配置默认生效。
下面看 name 属性,name 用来从 application.properties 中读取某个属性值。比如上面 Tomcat 的自动配置在配置文件为:
spring.datasource.type=org.apache.tomcat.jdbc.pool.DataSource
在 matchIfMissing 为 false 时,如果 name 值为空,则返回 false;如果 name 不为空,则将该值与 havingValue 指定的值进行比较,如果一样则返回 true,否则返回 false。返回 false 也就意味着自动配置不会生效。
但是如果看 HttpEncodingAutoConfiguration 类上的属性配置发现并没有完全按照上面所说的 name 和 havingValue 配合使用。它是通过“prefix+value”作为属性的名称来进行配置:
spring.http.encoding.enabled=true
其中 prefix 指定了配置的统一前缀“spring.http.encoding”,而 value 指定了具体的属性名称为“enabled”。这里并没有设置 havingValue 的值,如果 havingValue 未指定值,默认情况下在属性配置中设置的值为 true 则生效(如上配置),false 则不生效。
原文链接:《SPRING BOOT 中 @CONDITIONALONPROPERTY 使用详解》
--- 程序新视界:精彩和成长都不容错过 