Spring条件注解说明
条件判断
@Conditional
@Conditional是Spring4新提供的注解,它的作用指定一个或多个实现了Condition接口的类,只有满足这些类的所有matches()方法中的条件时,才会注册当前bean。
该注解可以用在类或方法上,用于控制bean的注册。用在方法上时,通常与@Bean
一起使用。
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
// 需要指定一个或多个实现了Condition接口的类,
// 只有满足这些类的所有matches()方法中的条件时,才会注册当前bean
Class<? extends Condition>[] value();
}
Condition接口定义如下:
@FunctionalInterface
public interface Condition {
// 判断是否满足条件
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
@ConditionalOnBean
只有在满足所有指定要求的bean已经包含在BeanFactory中时才匹配。 要匹配的条件必须满足所有要求,但当前的bean不必满足它们。
该注解可以用在类或方法上,用于控制bean的注册。用在方法上时,通常与@Bean
一起使用。
从下面该注解的声明可以看到,该注解的实现是依赖@Conditional(OnBeanCondition.class)的。
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnBeanCondition.class)
public @interface ConditionalOnBean {
// 按照Bean Class进行匹配
Class<?>[] value() default {};
// 按照Bean Class名称进行匹配
String[] type() default {};
// 按照Bean包含的注解进行匹配
Class<? extends Annotation>[] annotation() default {};
// 按照Bean的名称进行匹配
String[] name() default {};
// 搜索策略,是否考虑Context的层级关系(parent context)
SearchStrategy search() default SearchStrategy.ALL;
// 可能在其泛型参数中包含指定bean类型的其他类
Class<?>[] parameterizedContainer() default {};
}
搜索策略
public enum SearchStrategy {
// 只搜索当前的Context
CURRENT,
// 搜索所有的祖先Context,但不包含当前Context
ANCESTORS,
// 搜索所有的层级
ALL
}
@ConditionalOnMissingBean
与@ConditionalOnBean
判断的规则正好相反,当所有指定要求的bean不包含在BeanFactory中时才匹配。
当该注解用于一个有@Bean
注解的方法时,该注解的判断条件默认为该方法的返回值类型。
@Configuration
public class MyAutoConfiguration {
@ConditionalOnMissingBean
@Bean
public MyService myService() {
...
}
}
@ConditionalOnWebApplication
当当前应用为Web类型时,该方法才匹配。默认情况下匹配所有的Web类型,也可以通过type
字段指定要匹配的Web应用类型。
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnWebApplicationCondition.class)
public @interface ConditionalOnWebApplication {
// 匹配的Web应用类型
Type type() default Type.ANY;
// 可支持的应用类型
enum Type {
// 匹配任意Web应用类型
ANY,
// 只匹配Servlet Web应用类型
SERVLET,
// 只匹配“响应式”Web应用类型
REACTIVE
}
}
@ConditionalOnProperty
通过其两个属性name以及havingValue来实现的,其中name用来从application.properties中读取某个属性值。
如果该值为空,则返回false;
如果值不为空,则将该值与havingValue指定的值进行比较,如果一样则返回true;否则返回false。
如果返回值为false,则该configuration不生效;为true则生效。
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnPropertyCondition.class)
public @interface ConditionalOnProperty {
// name属性的别称
String[] value() default {};
// property名称的前缀,可有可无
String prefix() default "";
// 数组,property完整名称或部分名称(可与prefix组合使用,组成完整的property名称),与value不可同时使用
String[] name() default {};
// 指定properties期望的值,如果没有指定,则property必须不等于false
String havingValue() default "";
// 当指定的property未被设置时,property的默认值
boolean matchIfMissing() default false;
}
@AutoConfigureAfter
当前bean需要在@AutoConfigureAfter
中指定的bean初始化完成后才能进行初始化。
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE })
@Documented
public @interface AutoConfigureAfter {
// 应该已应用的自动配置类的名称
Class<?>[] value() default {};
// 应该已应用的自动配置类的名称
String[] name() default {};
}
@AutoConfigureBefore
当前bean需要在@AutoConfigureBefore
中指定的bean之前完成初始化,与@AutoConfigureAfter
用法相同。
@AutoConfigureOrder
是 @Order
注解的变种,用于指定AutoConfigure类之间的初始化次序,值越小,越优先被初始化。
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD })
@Documented
public @interface AutoConfigureOrder {
int DEFAULT_ORDER = 0;
// 顺序编号,默认为0
int value() default DEFAULT_ORDER;
}
@ConditionalOnClass
当前classpath下存在指定类时,才会实例化当前Bean,与@AutoConfigureAfter
用法相同。
@ConditionalOnMissingClass
当前classpath下不存在指定类时,才会实例化当前Bean,与@AutoConfigureAfter
用法相同。
@ConditionalOnExpression
当SpEL表达式为true的时候,才会实例化当前Bean。
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnExpressionCondition.class)
public @interface ConditionalOnExpression {
// 指定的SpEL表达式
String value() default "true";
}