可以从注解的名字我们可以看出来:如果当有某个属性或者某些属性时,并且属性的值匹配的时候,才去执行的某些操作,相当于是一个前置检查。
那么对应到spring中,应该如何使用呢?
首先我们看这个注解的内容
```java
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.springframework.boot.autoconfigure.condition;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Conditional;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@Conditional({OnPropertyCondition.class})
public @interface ConditionalOnProperty {
String[] value() default {};
String prefix() default "";
String[] name() default {};
String havingValue() default "";
boolean matchIfMissing() default false;
}
```
可以看到此处的@Target注解的作用域是ElementType(Class, interface (including annotation type), or enum declaration)以及METHOD也就是方法。所以可以看出来,这个注解可以用在类上面和方法上面。
所以就引申出来,当我们想让整个config下面的bean做前置校验的时候,那么这个注解就用在config类上面。比如
```java
/**
* weather config
*/
@Configuration
// 配置是否要开启后台查询功能,默认情况下需要配置开启
@ConditionalOnProperty(name = "weather.enable", havingValue = "true")
public class WeaConfig {
@Bean
RestTemplate restTemplate() {
return new RestTemplate();
}
}
```
如果此时想校验的是bean维度的,那么我们可以将该注解用在方法上面,比如
```java
/**
* weather config
*/
@Configuration
public class WeaConfig {
@Bean
// 配置是否要开启后台查询功能,默认情况下需要配置开启
@ConditionalOnProperty(name = "weather.enable", havingValue = "true")
RestTemplate restTemplate() {
return new RestTemplate();
}
}
```
所以在使用该注解过程中就会出现如下的几种情况
当我们的一个bean想使用注解ConditionalOnProperty下面的bean时,比如bean A 引用 bean B的时候。
- 没有配置对应的环境变量
bean A 创建的时候依赖 bean B,此时发现bean B对应的配置没有配置,则会报配置can not find错误。
```java
The following candidates were found but could not be injected:
- Bean method 'restTemplate' in 'WeaConfig' not loaded because @ConditionalOnProperty (weather.enable=true) did not find property 'weather.enable'
```
- 环境变量配置对了
如果配置对了,那么便可以正常启动了。
- 环境变量配错了
如果配置错了,比方我们期待这个变量是true,但是不小心写错了,配置成了false。那么就会报值匹配异常。
```java
The following candidates were found but could not be injected:
- Bean method 'restTemplate' in 'WeaConfig' not loaded because @ConditionalOnProperty (weather.enable=true) found different value in property 'weather.enable'
```
## `matchIfMissing`属性使用
用法:如果该属性值设置为true的时候,有且仅有当对应的name或者value不存在时,才会注入对应的bean,特别注意是不存在的时候,如果想判断值是否正确的话,请使用`havingValue`属性。
```java
/**
* weather config
*/
@Configuration
// 配置是否要开启后台查询功能,默认情况下需要配置开启
@ConditionalOnProperty(name = "weather.enable", matchIfMissing = true)
public class WeaConfig {
@Bean
RestTemplate restTemplate() {
return new RestTemplate();
}
}
```
上面的代码,当且仅当`weather.enable`配置在yml文件中不存在时,方可注入这个bean。否则将不注入容器。进而通过`@Autowired`尝试获取这个bean的时候会报错,使用`@Autowired(required = false)`时,会注入一个空的对象。
当`weather.enable`配置存在,即使是他本身的值时错误的,那么也是无法注入bean的。
可以看到提示,**found different value**。
关于该注解的使用就先分享这么多啦。
SpringBoot源码-@ConditionalOnProperty注解作用