@Conditional是spring-context从4.0版本新增的一个注解,主要作用是根据条件判断是否需要创建bean注册到容器中。
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
/**
* All {@link Condition Conditions} that must {@linkplain Condition#matches match}
* in order for the component to be registered.
*/
Class<? extends Condition>[] value();
}
value为Condition数组,数组的话就可以指定多个class,这几个class是与的关系。Condition是一个接口,只有一个matchs方法,定义如下:
@FunctionalInterface
public interface Condition {
/**
* Determine if the condition matches.
* @param context the condition context
* @param metadata the 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 the annotated component's registration
*/
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
顺便提一点之前工作中踩过的坑,@FunctionalInterface这个注解是java1.8才提供的,1.8里的接口可以提供default实现方法,基于1.8及以上的接口来实现某些接口时可能就不需要手动实现某些方法,此时如果把该功能开放给低版本的项目使用就会出现问题,类比spring或是其他组件的版本升级,同样也会遇到这样的问题,比如新版本有泛型老版本没有,此时就需要多注意一下。
继续Condition接口,该matches方法有两个参数ConditionContext context和AnnotatedTypeMetadata metadata,返回类型为boolean,如果返回true则注入bean,如果为false则不注入bean;其中ConditionContext提供了当前判断条件可使用的上下文,提供了多个方法,如getBeanFactory(),getEnvironment()等,方便springboot进行扩展;可以通过AnnotatedTypeMetadata判断注解是加载了类上还是方法上。
举个例子。
public class ConditionalDemo implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
// 此处可以自定义一些判断逻辑
// 例子默认返回true,表示可以创建bean并注入到容器中;如果为false,则不会注入
return true;
}
}
@Configuration
public class ConditionalTestConfigure {
/**
* 如果满足ConditionalDemo返回true,继续加载下面这个方法
**/
@Bean
@Conditional({ConditionalDemo.class})
public TestBean testBean(){
return new TestBean("This is testbean");
}
}
关于注解的解析等后面的文章一起介绍。