@ConditionalOnProperty 和@Conditional注解作用

Spring boot中的注解@ConditionalOnProperty

Spring boot中的注解@ConditionalOnProperty,可以通过配置文件中的属性值来判定configuration是否被注入.

配置类:
@Configuration
@ConditionalOnProperty(prefix = “x.y”, name = “test”, havingValue = “1”, matchIfMissing = true)
public class XConfiguration {…}

配置文件:
x.y.test=1

解释:
prefix为配置文件中的前缀.
name为配置的名字.
havingValue是与配置的值对比值,当两个值相同返回true,配置类生效.
matchIfMissing属性为true时,配置文件中缺少对应的value或name的对应的属性值,也会注入成功.

使用场景:
1、在日常使用中,定义一个mq的消费,在本地测试环境、预发环境、线上环境均对此定义,满足不同阶段的开发、测试、上线需要。通常接入一个新的mq消费,三个环境使用同一套mq配置,可以保障开发联调效率和上线后保证和预发环境一致。但在一个mq主题中,一个应用只能消费一次,就意味着三个环境同时运行,只能有一个环境生效,则可以使用 @ConditionalOnProperty 注解,通过配置控制。
2、过滤器等随部署环境变动的类,使用该注解方便调试。

@ConditionalOnProperty(
        prefix = "zn.com.interceptor",
        name = "enable",
        havingValue = "true"
)

还可以用在链式配置中,比如Spring MVC的过滤器和拦截器。

3、通过@ConditionalOnProperty来控制Configuration是否生效

@Configuration
//在application.properties配置"mf.assert",对应的值为true
@ConditionalOnProperty(prefix="mf",name = "assert", havingValue = "true")
public class AssertConfig {
    @Autowired
    private HelloServiceProperties helloServiceProperties;
    @Bean
    public HelloService helloService(){
        HelloService helloService = new HelloService();
        helloService.setMsg(helloServiceProperties.getMsg());
        return helloService;
    }
}

=====================

@ConditionalOnProperty和@Conditional的关系

@Conditional

需要自己实现match方法

@ConditionalOnProperty

可以通过属性配置值,通过配置实现,更灵活方便,不用写代码

附1:类似的有很多

@Conditional(ZiDingYiCondition.class)
@ConditionalOnProperty
@ConditionalOnBean
@ConditionalOnClass
@ConditionalOnResource
@ConditionalOnExpression
@ConditionalOnMissingBean

其中:

public class ZiDingYiCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata annotatedTypeMetadata) {
        Environment environment = context.getEnvironment();
        String activeProfiles = environment.getActiveProfiles()[0];
        return "online".equals(activeProfiles);
    }
}

附2:ConditionalOnProperty的定义,可以理解为通过值控制校验 条件。

/**
 * {@link Conditional} that checks if the specified properties have a specific value. By
 * default the properties must be present in the {@link Environment} and
 * not equal to {@code false}. The {@link #havingValue()} and
 * {@link #matchIfMissing()} attributes allow further customizations.
 * 

* The {@link #havingValue} attribute can be used to specify the value that the property * should have. The table below shows when a condition matches according to the property * value and the {@link #havingValue()} attribute: * * *

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Having values
Property Value{@code havingValue=""}{@code havingValue="true"}{@code havingValue="false"}{@code havingValue="foo"}
{@code "true"}yesyesnono
{@code "false"}nonoyesno
{@code "foo"}yesnonoyes
*

* If the property is not contained in the {@link Environment} at all, the * {@link #matchIfMissing()} attribute is consulted. By default missing attributes do not * match. *

* This condition cannot be reliably used for matching collection properties. For example, * in the following configuration, the condition matches if {@code spring.example.values} * is present in the {@link Environment} but does not match if * {@code spring.example.values[0]} is present. * *

 * @ConditionalOnProperty(prefix = "spring", name = "example.values")
 * class ExampleAutoConfiguration {
 * }
 * 
* * It is better to use a custom condition for such cases. * * @author Maciej Walkowiak * @author Stephane Nicoll * @author Phillip Webb * @since 1.1.0 */
@Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE, ElementType.METHOD }) @Documented @Conditional(OnPropertyCondition.class) public @interface ConditionalOnProperty { /** * Alias for {@link #name()}. * @return the names */ String[] value() default {}; /** * 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 ""; /** * 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} *

* 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 {}; /** * The string representation of the expected value for the properties. If not * specified, the property must not be equal to {@code false}. * @return the expected value */ String havingValue() default ""; /** * 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; }

其中:

/**
 * {@link Condition} that checks if properties are defined in environment.
 *
 * @author Maciej Walkowiak
 * @author Phillip Webb
 * @author Stephane Nicoll
 * @author Andy Wilkinson
 * @since 1.1.0
 * @see ConditionalOnProperty
 */
@Order(Ordered.HIGHEST_PRECEDENCE + 40)
class OnPropertyCondition extends SpringBootCondition {

	@Override
	public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
		List<AnnotationAttributes> allAnnotationAttributes = annotationAttributesFromMultiValueMap(
				metadata.getAllAnnotationAttributes(ConditionalOnProperty.class.getName()));
		List<ConditionMessage> noMatch = new ArrayList<>();
		List<ConditionMessage> match = new ArrayList<>();
		for (AnnotationAttributes annotationAttributes : allAnnotationAttributes) {
			ConditionOutcome outcome = determineOutcome(annotationAttributes, context.getEnvironment());
			(outcome.isMatch() ? match : noMatch).add(outcome.getConditionMessage());
		}
		if (!noMatch.isEmpty()) {
			return ConditionOutcome.noMatch(ConditionMessage.of(noMatch));
		}
		return ConditionOutcome.match(ConditionMessage.of(match));
	}
	//略
}

你可能感兴趣的:(spring,注解,java)