1 问题来源
- 对于 @ConditionOnBean 注解的匹配成功的条件不是很清晰
- 随着项目的复杂化,各个 bean 直接的关联也越来越复杂,这样极有可能在使用 @ConditionOnBean 注解时,并不能达到预期的目的
- 预要清晰的知道使用的 @ConditionOnBean 注解的预期效果,必须了解清楚它的匹配的时机和匹配的成功的条件
2 @ConditionOnBean 注解匹配的时机
- 在 Springboot 源码分析 —— refreshContext() 解析 一文中,详细介绍了配置类的解析过程
- 在其中可以看出在 解析 ConfigurationClass 和 加载 BeanDefinition 这两个阶段都使用了条件注解进行配置类过滤
- 过滤的关键是 ConditionEvluator#shouldSkip 方法,源码分析如下
- 在 解析 ConfigurationClass 阶段,phase 参数是 PARSE_CONFIGURATION
- 在 加载 BeanDefinition 阶段,phase 参数是 REGISTER_BEAN
- 通过源码分析可知:@ConditionOnBean 注解是在 加载 BeanDefinition 阶段,才去匹配的
public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) {
if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
return false;}
if (phase == null) {
if (metadata instanceof AnnotationMetadata &&
ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {
return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);
}
return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);
}
List<Condition> conditions;
AnnotationAwareOrderComparator.sort(conditions);
for (Condition condition : conditions) {
ConfigurationPhase requiredPhase = null;
if (condition instanceof ConfigurationCondition) {
requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
}
if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) {
return true;
}
}
return fals