Conditional 注解

简单使用

以 @ConditionalOnProperty 注解为例,新建组件 A,当配置中存在 store.xianglin.condition 配置项时,向容器中注册 A。

@ConditionalOnProperty("store.xianglin.condition")
@Component
public class A {
}

@RunWith(SpringRunner.class)
@SpringBootTest
public class TestA {
    @Resource
    ApplicationContext context;

    @Test
    public void testA() {
        var bean = context.getBean(A.class);
        Assert.assertNotNull(bean);
    }
}
store.xianglin.condition=a

store.xianglin.condition 配置有值时,测试通过。

原理分析

@ConditionalOnProperty 注解上有 @Conditional(OnPropertyCondition.class)。

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnPropertyCondition.class)
public @interface ConditionalOnProperty {
	String[] value() default {};
}

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
  // 配置的所有Condition 都满足时向容器中注册组件
	Class<? extends Condition>[] value();
}

Condition 的定义是。

@FunctionalInterface
public interface Condition {
  // 满足条件时返回 true
	boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);

}

自定义 Conditional 注解

创建类 MyCondition 实现 Condition 接口,在 matches 方法中判断配置中存在相应配置项值时返回 true。

public class MyCondition implements Condition {
  
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        var value = (String[]) metadata.getAnnotationAttributes("store.xianglin.sb2.condi.MyConditionAnnotation").get("value");
        for (String property : value) {
            if (!StringUtils.isEmpty(context.getEnvironment().getProperty(property))) {
                return true;
            }
        }
        return false;
    }
}

创建注解 MyConditionAnnotation 并使用 @Conditional 注解标注。

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(MyCondition.class)
public @interface MyConditionAnnotation {
    String[] value() default {};
}