这篇文章介绍Spring 4的@Conditional注解。
一、在Spring的早期版本你可以通过以下方法来处理条件问题
- 3.1之前的版本,使用Spring Expression Language(SPEL)。
- 3.1版本有个新特性叫profile,用来解决条件问题。
1.1、Spring Expression Language(SPEL)
SPEL有一个三元运算符(if-then-else)可以在配置文件中当作条件语句,如下:
testBean的prop动态依赖于flag的值。
1.2、使用Profile
二、使用@Conditional
官方文档定义:“Indicates that a component is only eligible for registration when all specified conditions match”,意思是只有满足一些列条件之后创建一个bean。
除了自己自定义Condition之外,Spring还提供了很多Condition给我们用
@ConditionalOnClass : classpath中存在该类时起效 @ConditionalOnMissingClass : classpath中不存在该类时起效 @ConditionalOnBean : DI容器中存在该类型Bean时起效 @ConditionalOnMissingBean : DI容器中不存在该类型Bean时起效 @ConditionalOnSingleCandidate : DI容器中该类型Bean只有一个或@Primary的只有一个时起效 @ConditionalOnExpression : SpEL表达式结果为true时 @ConditionalOnProperty : 参数设置或者值一致时起效 @ConditionalOnResource : 指定的文件存在时起效 @ConditionalOnJndi : 指定的JNDI存在时起效 @ConditionalOnJava : 指定的Java版本存在时起效 @ConditionalOnWebApplication : Web应用环境下起效 @ConditionalOnNotWebApplication : 非Web应用环境下起效
@Conditional定义
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE, ElementType.METHOD) public @interface Conditional{ Class [] value();}
@Conditional注解主要用在以下位置:
- 类级别可以放在注标识有@Component(包含@Configuration)的类上
- 作为一个meta-annotation,组成自定义注解
- 方法级别可以放在标识由@Bean的方法上
如果一个@Configuration的类标记了@Conditional,所有标识了@Bean的方法和@Import注解导入的相关类将遵从这些条件。
condition接口定义如下:
public interface Condition { /** * Determine if the condition matches. * @param context the condition context * @param metadata metadata of the { @link org.springframework.core.type.AnnotationMetadata class} * or { @link org.springframework.core.type.MethodMetadata method} being checked. * @return { @code true} if the condition matches and the component can be registered * or { @code false} to veto registration. */ boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);}
下面看一个例子:
结果: