当前位置:   article > 正文

Spring Boot学习(二十二):@ConditionalOnProperty和@ConditionalOnExpression控制加载_@conditionalonexpression("#{systemproperties['my.p

@conditionalonexpression("#{systemproperties['my.property'] != null}")

@ConditionalOnProperty

@ConditionalOnProperty的作用是判断一个Property属性,是否符合我们的条件,符合则让该注解修饰的类或者方法生效,否则不生效

我们在Spring Boot中可以通过@ConditionalOnProperty来控制Configuration配置类是否生效


@ConditionalOnProperty源码:

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnPropertyCondition.class)
public @interface ConditionalOnProperty {

	/**数组,获取对应property名称的值,与name不可同时使用。
	 * Alias for {@link #name()}.
	 * @return the names
	 */
	String[] value() default {};

	/**property名称的前缀,有时为了方便,可以使用该属性
	 * A prefix that should be applied to each property. The prefix automatically ends
	 * with a dot if not specified. A valid prefix is defined by one or more words
	 * separated with dots (e.g. {@code "acme.system.feature"}).
	 * @return the prefix
	 */
	String prefix() default "";

	/**数组,property完整名称或部分名称(可与prefix组合使用,组成完整的property名称),与value不可同时使用。
	 * The name of the properties to test. If a prefix has been defined, it is applied to
	 * compute the full key of each property. For instance if the prefix is
	 * {@code app.config} and one value is {@code my-value}, the full key would be
	 * {@code app.config.my-value}
	 * <p>
	 * Use the dashed notation to specify each property, that is all lower case with a "-"
	 * to separate words (e.g. {@code my-long-property}).
	 * @return the names
	 */
	String[] name() default {};

	/**可与name组合使用,比较获取到的属性值与havingValue给定的值是否相同,相同才加载配置。
	 * The string representation of the expected value for the properties. If not
	 * specified, the property must <strong>not</strong> be equal to {@code false}.
	 * @return the expected value
	 */
	String havingValue() default "";

	/**缺少该property时是否可以加载。如果为true,没有该property也会正常加载;反之报错
	 * Specify if the condition should match if the property is not set. Defaults to
	 * {@code false}.
	 * @return if should match if the property is missing
	 */
	boolean matchIfMissing() default false;

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

我们可以使用@ConditionalOnProperty来控制配置类是否生效

使用例子

1、在配置文件添加一个属性,用来控制配置是否生效

#是否开启配置文件
open.Configuration=true
  • 1
  • 2

2、创建一个bean类

@Data
public class Student {

    private String name;


    private String age;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

3、创建一个配置类,注册Student的bean

@Configuration
@ConditionalOnProperty(name = "open.Configuration",havingValue = "true")
public class TestConfig {

    @Bean
    public Student student(){
        Student student=new Student();
        System.out.println("-------Student类初始化-------");
        return student;
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

启动项目,可以看到输出语句
在这里插入图片描述

把属性设置成false(或者其他字段),启动

open.Configuration=false

可以看到没有输出,说明配置类已经失效

在这里插入图片描述

流程:通过@ConditionalOnProperty的两个属性name以及havingValue来实现,其中name用来从application.properties中读取某个属性值。
如果该值为空,则直接返回false,不让配置类生效。如果值不为空,则将该值与havingValue指定的值进行比较,如果一样则返回true;否则返回false。

如果只使用@ConditionalOnProperty的name属性,那么当配置文件中只要出现xxx时(内容为空,同样也是有效的),则该配置生效。

@ConditionalOnProperty(name = “xxx”)


@ConditionalOnExpression

当我们有多个配置需要控制是否生效时候,@ConditionalOnProperty就显示有点不能满足我们的需求的

//@ConditionalOnProperty虽然支持多个name属性名,但它是逻辑与的。即需要name数值的所有属性都满足havingValue值才能使配置生效

@ConditionalOnProperty(name={"config1.enable","config.all"}, havingValue="true")
  • 1

这时候,我们就可以使用另一个更灵活的注解了,那就是@ConditionalOnExpression注解

@ConditionalOnExpression的判断方式是里面的表达式,执行Spel表达式,根据返回的true/false来判断是否满足条件,满足表达式则生效,如我们上面的例子,可以改成以下的样子,功能是一样的

@Configuration
@ConditionalOnExpression("${open.Configuration}")
public class TestConfig {

    @Bean
    public Student student(){
        Student student=new Student();
        System.out.println("-------注册Student类-------");
        return student;
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

ConditionalOnExpression的表达式

${属性名}:为取出配置中的某个属性值,当表达式为${open.Configuration}时,open.Configuration的值只能是true或者false,其他值会报错。因为它是直接判断该表达式是否为true或者false,即boolean类型

#是否开启配置文件
open.Configuration=false
  • 1
  • 2

注意:使用${open.Configuration},如果在配置文件找不到该属性(即不写)也会抛出异常

当我们需要配置文件存在某属性并且该属性值于我们设定的值一样可以使用以下的方法。字符串比较使用equals,数值类型使用==

例如以下的表达式,只有我们在配置文件存在open.Configuration=open才会生效,open.Configuration=xxx(其他字符)或者不写都不会生效。

@ConditionalOnExpression(" '${open.Configuration}'.equals('open')")
  • 1

下面的表达式表示,只有存在open.Configuration并且值等于1才会生效

@ConditionalOnExpression(" ${open.Configuration}==1")
  • 1

注意:假如我们使用" ${open.Configuration}==1"比较属性值,在配置文件填写的是字符,那么会抛出异常,因为类型不一样。

如:

open.Configuration=xxx

运行会抛出

Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'xxx' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public or not valid?
  • 1

并且ConditionalOnExpression表达式支持与或的逻辑运算

或逻辑表达式,下面的表达式表示只要open.Configuration或者open.bean.config有一个为true,则生效

@ConditionalOnExpression(" ${open.Configuration}||${open.bean.config}")
  • 1

其实,我们还可以生效的属性值也放到配置文件,这样我们就可以在配置文件进行修改

如:

#配置属性
open.Configuration=yes
#生效的属性值
configguration.field=yes

ConditionalOnExpression表达式

@ConditionalOnExpression(" '${open.Configuration}'.equals('${configguration.field}')")
  • 1
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/88232
推荐阅读
相关标签
  

闽ICP备14008679号