你真的会用 @ConditionalOnXXX 注解吗?

1. @ConditionalOnBean

IOC 容器存在某个 bean 时

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnBeanCondition.class)
public @interface ConditionalOnBean {

    // bean 类的类型
    Class<?>[] value() default {};

    // bean 类的类型名称(类路径,例如:String 类是 "java.lang.String")
    String[] type() default {};

    // bean 上拥有指定注解
    Class<? extends Annotation>[] annotation() default {};

    // bean 的名称
    String[] name() default {};

    // 容器层级
    // ALL:所有容器
    // ANCESTORS:所有祖先容器,但不包含当前容器
    // CURRENT:仅当前容器
    SearchStrategy search() default SearchStrategy.ALL;

    // 1.1 下面扩展
    Class<?>[] parameterizedContainer() default {};

}
1.1 parameterizedContainer 扩展:
  • 指定 bean 类的类型:泛型类

  • 匹配规则:存在某个 bean 为 A ,A 的类型和 parameterizedContainer 指定的泛型类的类型一致(可以是它的实现类或继承子类),且 A 的泛型参数是 @ConditionalOnBean 注解的 bean 的类型

  • 简单例子:

    @Configuration
    public class TestConfiguration {
    
        // 该 bean 存在时, apple 初始化到 IOC 容器
        @Bean
        public Set<Apple> set1() {
            return new HashSet<>();
        }
    
        // 该 bean 存在时, apple 不可以初始化到 IOC 容器
        @Bean
        public Set<Integer> set2() {
            return new HashSet<>();
        }
        
        // 该 bean 存在时, apple 不可以初始化到 IOC 容器
        @Bean
        public List<Apple> list1() {
            return new ArrayList<>();
        }
    
        @Bean
        @ConditionalOnBean(parameterizedContainer = Set.class)
        public Apple apple() {
            return new Apple();
        }
    }
    

2. @ConditionalOnMissingBean

IOC 容器不存在某个 bean 时

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnBeanCondition.class)
public @interface ConditionalOnMissingBean {

    // 可以被忽略的 bean 类的类型
    Class<?>[] ignored() default {};

    // 可以被忽略的 bean 类的类型名称(类路径)
    String[] ignoredType() default {};

    // 其他属性和 @ConditionalOnBean 的一样

}

3. @ConditionalOnClass

classpath 下存在某个 class 时

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class)
public @interface ConditionalOnClass {

    // 类的类型
    Class<?>[] value() default {};

    // 类的类型名称(类路径)
    String[] name() default {};

}

4. @ConditionalOnMissingClass

classpath 下不存在某个 class 时

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class)
public @interface ConditionalOnMissingClass {

    // 类的类型名称(类路径)
    String[] value() default {};

}

5. @ConditionalOnWebApplication

运行在 Web 应用时

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnWebApplicationCondition.class)
public @interface ConditionalOnWebApplication {

    // Web 应用的类型
    Type type() default Type.ANY;

    enum Type {

        // 任何类型
        ANY,

        // 传统 MVC
        SERVLET,

        // 响应式
        REACTIVE

    }

}

6. @ConditionalOnNotWebApplication

不运行在 Web 应用时

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnWebApplicationCondition.class)
public @interface ConditionalOnNotWebApplication {
    // 没有属性字段,表示不运行在任何 Web 应用
}

7. @ConditionalOnProperty

相应配置属性满足条件时

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnPropertyCondition.class)
public @interface ConditionalOnProperty {

    // 完整配置名称
    // 部分配置名称,prefix + value 配合使用时组成完成配置名称
    // value 和 name 不可同时使用
    String[] value() default {};

    // 配置名称前缀
    String prefix() default "";

    // 完整配置名称
    // 部分配置名称,prefix + name 配合使用时组成完成配置名称
    String[] name() default {};

    // 比较指定的配置属性值与 havingValue 的,相等时生效
    String havingValue() default "";

    // 指定的配置属性值不存在时
    // true:生效
    // false:不生效
    boolean matchIfMissing() default false;

}

8. @ConditionalOnResource

指定路径下的资源存在时

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnResourceCondition.class)
public @interface ConditionalOnResource {

    // 资源路径,例如:"classpath:META-INF/services/javax.validation.spi.ValidationProvider"
    String[] resources() default {};

}

9. @ConditionalOnSingleCandidate

指定 bean 在 beanFactory 中只有一个,或者存在多个时指定了首选(@Primay)bean 时

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnBeanCondition.class)
public @interface ConditionalOnSingleCandidate {

    // bean 类的类型
    Class<?> value() default Object.class;

    // bean 类的类型名称(类路径)
    String type() default "";

    // 容器层级
    // ALL:所有容器
    // ANCESTORS:所有祖先容器,但不包含当前容器
    // CURRENT:仅当前容器
    SearchStrategy search() default SearchStrategy.ALL;

}

10. @ConditionalOnCloudPlatform

指定的云平台激活时

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnCloudPlatformCondition.class)
public @interface ConditionalOnCloudPlatform {

    // 云平台类型
    CloudPlatform value();

}

11. @ConditionalOnExpression

满足指定 SpEL 表达式时

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnExpressionCondition.class)
public @interface ConditionalOnExpression {

    // SpEL 表达式,例如:"'${mq.comsumer}'.equals('rabbitmq')"
    // 默认 "true" 表示生效
    String value() default "true";

}

12. @ConditionalOnJava

运行在指定版本的 JVM 时

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnJavaCondition.class)
public @interface ConditionalOnJava {

    // 版本匹配程度
    Range range() default Range.EQUAL_OR_NEWER;

    // Java 版本
    JavaVersion value();

    enum Range {

        // 等于或高于指定版本
        EQUAL_OR_NEWER,

        // 低于指定版本
        OLDER_THAN

    }

}

13. @ConditionalOnJndi

通过 JNDI 加载后

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnJndiCondition.class)
public @interface ConditionalOnJndi {

    // 指定资源,例如:"java:/JmsXA"
    // 指定多个,存在一个就满足条件
    String[] value() default {};

}

JNDI了解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值