述
在我们 Spring Boot 项目中,很多地方都用到了 @Conditional
注解用来指定一些条件, 这个注解的作用是根据是否满足某一个特定的条件来决定是否创建某个 Bean ,这个注解的存在也是 Spring Boot 实现自动配置的关键基础能力,比如我们在 web 工厂类加载的部分就遇到过这个注解
常见的 @Conditional 注解
注解 | 作用 |
---|---|
@ConditionalOnBean | 当某个Bean存在的情况下 |
@ConditionalOnMissingBean | 当某个Bean不存在的情况下 |
@ConditionalOnClass | 当某个类存在的情况下 |
@ConditionalOnMissingClass | 当某个类不存在的情况下 |
@ConditionalOnWebApplication | 处于web环境下 |
@ConditionalOnProperty | 当某个 property 存在的时候 |
@ConditionalOnNotWebApplication | 不处于web环境的情况下 |
@ConditionalOnJava | 在特定的Java版本下 |
动手实践
了解了 @Condition
注解的作用之后,我们来写一个类实际使用测试一下
首先新建一个类, 如下1
2
3
4@Component
@ConditionalOnProperty("com.test")
public class ConditionTest {
}
这里首先是 @Component
注解, 表示要注入到容器中,然后用到了 @ConditionalOnProperty
注解,表示 com.test
这个属性要在环境变量中存在
然后写个测试类看一下
1 | @SpringBootTest |
这里直接运行, 从容器中找这个类, 看一下输出结果
这里可以看到,我们在容器中是找不到这个类的,因为在环境变量中并没有 com.test
这个属性
然后我们在 application
配置文件中配置一下这个属性1
2com:
test: test
再次运行,看一下输出结果
这次就成功注入到容器中了
原理分析
来看一下上面用的 @ConditionOnProperty
注解
这里其实用了一个 @Condition
注解, 点进去
这个注解有一个属性,是一个类,这个类必须是 Condition
的子类,进入这个类看一下
可以看到这个接口只有一个方法 matches()
这个方法返回是 true 的话表示符合条件,就会被注入到容器中,如果是 false 则不会被注入到容器中
我们这里可以看一下他这个注解是怎么判断的
@ConditionOnProperty
这个注解用的是 @Conditional(OnPropertyCondition.class)
进入 OnPropertyCondition
这个类, 这个类是继承自 SpringBootCondition
这个抽象类, 所以我们先看一下 SpringBootCondition.matches
这个方法
这里可以看到重点的判断方法还是 getMatchOutcome()
这个方法,这个方法是具体子类实现的, 然后回到 OnPropertyCondition
看一下这个方法
这里的判断是在 determineOutcome()
这个方法当中,点进去
这里首先做了一个包装,然后调用它的 collectProperties()
方法做判断
这里就是调用环境变量,然后做具体的验证
经过上面的分析,我们是不是可以仿着这个,自己实现一个 @Condition
注解
自定义实现 @Condition 注解
首先我们需要一个类,实现 Condition
然后重写他的 matches()
方法,代码如下
1 | public class MyCondition implements Condition { |
然后就需要创建一个注解
1 | @Retention(RetentionPolicy.RUNTIME) |
这里加上 @Conditional
注解,指定我们刚刚创建的类,然后就可以在之前的 ConditionTest
类中使用测试了
1 | @Component |
这里整体作用就是 com.test1
和 com.test2
这两个属性都有值的情况下,这个类才会被注入到容器中
总结
关于 @Condition
注解的使用就介绍到这里,下面做一个总结
作用:
- 通过
@Condition
注解可以实现根据是否满足某一个特定的条件来决定是否创建某个 Bean
自定义 @Condition
注解的流程
- 实现一个自定义注解并且引入
@Condition
注解 - 实现
Condition
接口,并且重写matches()
方法,符合条件就返回 true - 自定义注解引入上面创建的
Condition
接口的实现