美文网首页
SpringBoot 中通过注解控制Configuration是

SpringBoot 中通过注解控制Configuration是

作者: 久伴我还是酒伴我 | 来源:发表于2020-03-29 15:16 被阅读0次

简介

在日常开发中,经常使用各种各样的配置项,配置项需要通过注解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初始化等。

相关文章

网友评论

      本文标题:SpringBoot 中通过注解控制Configuration是

      本文链接:https://www.haomeiwen.com/subject/xaxuuhtx.html