简介
在日常开发中,经常使用各种各样的配置项,配置项需要通过注解Configuration注解来声明该类为配置项,但是此配置项为全局配置项,比如在某种情况下不想让此配置项生效,该怎么处理呢?今天咱们来简单看下注解@ConditionalOnProperty。
常用配置项
设置跨域请求
@Configuration
public class CorsConfig {
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
//允许任何域名访问
corsConfiguration.addAllowedOrigin("*");
//允许任何header访问
corsConfiguration.addAllowedHeader("*");
//允许任何方法访问
corsConfiguration.addAllowedMethod("*");
return corsConfiguration;
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", buildConfig());
return new CorsFilter(source);
}
}
Swagger 配置
/**
* Swagger配置类
*
* @author yorke
* @date 2016/7/27.
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
ParameterBuilder tokenPar1 = new ParameterBuilder();
ParameterBuilder tokenPar2= new ParameterBuilder();
List<Parameter> pars = new ArrayList<Parameter>();
tokenPar1.name("X-KXL-Company-ID").description("令牌-公司id").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
tokenPar2.name("X-KXL-User-ID").description("令牌-用户id").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
pars.add(tokenPar1.build());
pars.add(tokenPar2.build());
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.kingxunlian"))
.paths(PathSelectors.any())
.build()
.globalOperationParameters(pars)
.apiInfo(apiInfo());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Product Service API")
.description("Product Service API")
.termsOfServiceUrl("xltec.cc")
.version("1.0")
.build();
}
}
Xxl-Job,Mybatis-Plus 等等,应该开发的同学都会知道。
在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注解类源码如下
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnPropertyCondition.class)
public @interface ConditionalOnProperty {
// 数组,获取对应property名称的值,与name不可同时使用
String[] value() default {};
// 配置属性名称的前缀,比如spring.http.encoding
String prefix() default "";
// 数组,配置属性完整名称或部分名称
// 可与prefix组合使用,组成完整的配置属性名称,与value不可同时使用
String[] name() default {};
// 可与name组合使用,比较获取到的属性值与havingValue给定的值是否相同,相同才加载配置
String havingValue() default "";
// 缺少该配置属性时是否可以加载。如果为true,没有该配置属性时也会正常加载;反之则不会生效
boolean matchIfMissing() default false;
}
使用方法
通过其两个属性name以及havingValue来实现的,其中name用来从application.properties中读取某个属性值。
如果该值为空,则返回false;
如果值不为空,则将该值与havingValue指定的值进行比较,如果一样则返回true;否则返回false。
如果返回值为false,则该configuration不生效;为true则生效。
代码
配置文件Properties中的配置项,当该配置项为false时,CorsConfig配置类生效
deploy.model.isFirst=false
@ConditionalOnProperty(prefix = "deploy.model",name = "isFirst",havingValue = "false")
@Configuration
public class CorsConfig {
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
//允许任何域名访问
corsConfiguration.addAllowedOrigin("*");
//允许任何header访问
corsConfiguration.addAllowedHeader("*");
//允许任何方法访问
corsConfiguration.addAllowedMethod("*");
return corsConfiguration;
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", buildConfig());
return new CorsFilter(source);
}
}
结束语
自动装配是springboot中一特性,springboot在程序初始化时可以根据classpath类、property属性、context中实例、以及运行容器特征等各种动态条件,来按需初始化相应的bean并交付给终端使用。
此外SpringBoot还提供了其他更多的condition判断,按需使用即可。在SpringBean容器初始化之前、Envrionment准备就绪之后,将根据spring.factories文件中指定的AutoConfiguration类列表逐个解析上述Condition,并在稍后有序加载、初始化相关bean。
1、@ConditionalOnBean:如果此Bean实例已存在,则执行(如果修饰在class上,则此类加载;如果修饰在方法上 ,则此方法执行)。通常用于限定“如果必备的bean已经被初始化时,才会自动装备当前实例”。
2、@ConditionalOnMissingBean:如果此Bean实例尚未被初始时,则执行。
3、@ConditionalOnClass:如果classpath中存在此类(且可被加载)时,则执行。
4、@ConditionalOnMissingClass:如果class中不存在此类时,则执行。
5、@ConditionalOnProperty:如果Envrionment中存在此property、或者相应的property参数值匹配时,则执行。比如springboot中,各种内置的组件是否enabled,就是根据此条件判断。
6、@ConditionalOnWebApplication:如果当前容器为WEB时,则执行。比如初始化springMVC、restTemplate、各种endpoint初始化等。