Spring注解之@Conditional使用解析
@Conditional
@Conditional注解可以说是SpringBoot的条件注解,表示组件只有在所有指定条件都匹配时才有资格注册,条件是可以在 bean 定义注册之前以编程方式确定的任何状态。
@Conditional注解可以通过以下任何方式使用:
- 作为直接或间接使用@Component注解的任何类的类型级注释,包括@Configuration类
- 作为元注解,用于编写自定义构造型注释
- 作为任何@Bean方法的方法级注解
如果@Configuration类被标记为@Conditional ,那么与该类关联的所有@Bean方法、 @Import 注解和@ComponentScan注解都将受制于条件。
SpringBoot @ConditionalOn*
SpringBoot提供的@ConditionalOn*的注解都是基于@Conditional注解实现
@ConditionalOnBean
仅当满足所有指定要求的 bean 已包含在BeanFactory中时才匹配的Conditional 。
必须满足所有要求才能匹配条件,但不必由同一个 bean 满足。
@ConditionalOnClass
仅当指定的类在类路径上时才匹配的Conditional 。
可以在@Configuration类上安全地指定value() ,因为在加载类之前使用 ASM 解析注释元数据。
放置在@Bean方法上时需要格外小心,考虑将条件隔离在单独的Configuration类中,特别是如果方法的返回类型与value()中的值匹配。
@ConditionalOnCloudPlatform
当指定的云平台处于活动状态时匹配的Conditional。
@ConditionalOnExpression
取决于 SpEL 表达式的值的条件元素的配置注解。
@ConditionalOnJava
根据运行应用程序的 JVM 版本匹配的Conditional。
@ConditionalOnJndi
基于 JNDI InitialContext的可用性和查找特定位置的能力匹配的Conditional。
@ConditionalOnMissingBean
仅当BeanFactory中已不包含满足指定要求的 bean 时才匹配的Conditional 。 条件匹配不必满足任何要求,并且同一bean不必满足这些要求。
@ConditionalOnMissingClass
仅当指定的类不在类路径上时才匹配的Conditional。
@ConditionalOnNotWebApplication
仅在应用程序上下文不是 Web 应用程序上下文时匹配的Conditional。
@ConditionalOnProperty
检查指定属性是否具有特定值的Conditional 。 默认情况下,属性必须存在于Environment中并且不等于false 。 havingValue()和matchIfMissing()属性允许进一步自定义。havingValue属性可用于指定属性应具有的值。如果该属性根本不包含在Environment中,则matchIfMissing()属性。 默认情况下,缺少的属性不匹配。
@ConditionalOnResource
仅当指定资源在类路径上时才匹配的Conditional 。
@ConditionalOnSingleCandidate
仅当指定类的 bean 已包含在BeanFactory中并且可以确定单个候选者时才匹配的Conditional 。 如果BeanFactory中已包含多个匹配的 bean 实例但已定义主要候选者,则条件也将匹配; 本质上,如果自动装配具有定义类型的 bean,则条件匹配将成功。 该条件只能匹配到目前为止已由应用程序上下文处理的 bean 定义,因此,强烈建议仅在自动配置类上使用此条件。 如果候选 bean 可能由另一个自动配置创建,请确保使用此条件的 bean 在之后运行。
@ConditionalOnWebApplication
当应用程序是 Web 应用程序时匹配的Conditional 。 默认情况下,任何 Web 应用程序都会匹配,但可以使用type()属性缩小范围。
@ConditionalOn*实现原理
以@ConditionalOnBean为例
@Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @Conditional(OnBeanCondition.class) public @interface ConditionalOnBean{ //... }
@Conditional作为元注解,OnBeanCondition继承SpringBootCondition,SpringBootCondition
实现自org.springframework.context.annotation.Condition。
public abstract class SpringBootCondition implements Condition { private final Log logger = LogFactory.getLog(getClass()); @Override public final boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { String classOrMethodName = getClassOrMethodName(metadata); try { ConditionOutcome outcome = getMatchOutcome(context, metadata); logOutcome(classOrMethodName, outcome); recordEvaluation(context, classOrMethodName, outcome); return outcome.isMatch(); } catch (NoClassDefFoundError ex) { } } } //org.springframework.boot.autoconfigure.condition.OnBeanCondition @Override public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { ConditionMessage matchMessage = ConditionMessage.empty(); if (metadata.isAnnotated(ConditionalOnBean.class.getName())) { BeanSearchSpec spec = new BeanSearchSpec(context, metadata, ConditionalOnBean.class); MatchResult matchResult = getMatchingBeans(context, spec); if (!matchResult.isAllMatched()) { String reason = createOnBeanNoMatchReason(matchResult); return ConditionOutcome.noMatch(ConditionMessage .forCondition(ConditionalOnBean.class, spec).because(reason)); } matchMessage = matchMessage.andCondition(ConditionalOnBean.class, spec) .found("bean", "beans") .items(Style.QUOTE, matchResult.getNamesOfAllMatches()); } //... return ConditionOutcome.match(matchMessage); }
到此这篇关于Spring注解之@Conditional使用解析的文章就介绍到这了,更多相关@Conditional使用解析内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
mybatis如何设置useGeneratedKeys=true
这篇文章主要介绍了mybatis如何设置useGeneratedKeys=true,具有很好的参考价值,希望对大家有所帮助。2022-01-01
最新评论