springboot之@Conditional和@ConditionalXXX

编程

spring boot 最让我们惊艳的特性应该就是自动配置。当从你引入了spring-boot-starter-xx那一刻开始,spring boot 在后面就为我们做了很多工作,具体整个流程是怎么组织的,我们以后再说。今天我们就来看下spring boot 中的一个决定bean或者配置类能否被注入容器的关键注解@Conditional。


@Conditional--条件注解。我们看下这个注解的定义

@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();

}

可以看到这个注解可以使用在类和方法上。一般情况情况下我们不直接使用这个注解,而是使用@ConditionalOnXXX(例如@ConditionalOnBean)。那么@ConditionalOnXXX和@Conditional有什么关系呢。实际上@ConditionalOnXXX主要是利用了spring 的注解的派生性质(暂时没找到更好的术语)。什么是注解的派生性呢,就是@ConditionalOnXXX 具有@Conditional的特性但是又可以有自己的独特的特点。


spring boot 中都提供了哪些条件注解给我们使用呢

Class Conditions

  • @ConditionalOnClass

 @Bean

@ConditionalOnClass(name = "com.google.gson.Gson")

public OrderTest orderTest(){

OrderTest orderTest = new OrderTest();

System.out.println("因为引入了gson,所以初始化");

return orderTest;

}

因为classpath中含有了Gson类,所以会初始化。注意注解中value 与 name 的区别

  • @ConditionalOnMissingClass

    @Bean

@ConditionalOnMissingClass(value = "com.google.gson.Gson")

public OrderTest orderTest2(){

OrderTest orderTest = new OrderTest();

System.out.println("因为没有引入了gson,所以初始化");

return orderTest;

}

因为classpath中没有Gson类,所以会初始化。

Bean Conditions

  • @ConditionalOnBean

    @Bean

@ConditionalOnBean(type = {"com.google.gson.Gson"})

public OrderTest orderTest3(){

OrderTest orderTest = new OrderTest();

System.out.println("因为容器中有gson,所以初始化");

return orderTest;

}

  • @ConditionalOnMissingBean

    @Bean

@ConditionalOnMissingBean(type = {"com.google.gson.Gson"})

public OrderTest orderTest4(){

OrderTest orderTest = new OrderTest();

System.out.println("因为容器中没有gson,所以初始化");

return orderTest;

}

注意的是与Class condition的区别,一个是类路径中是否包含一个是容器中是否包含。

Property Conditions

  • @ConditionalOnProperty

    @Bean

@ConditionalOnProperty(prefix = "test.auto.login",name = "aop",havingValue = "YES")

public OrderTest orderTest4(){

OrderTest orderTest = new OrderTest();

System.out.println("当属性值等于YES时才会注入");

return orderTest;

}

当环境变量中的test.auto.login.aop=YES时才会注入。这就给我们很多的操作空间,定义start组件时,可以把是否注入的决定权交给使用方。

SpEL Expression Conditions

  • @ConditionalOnExpression

    @Bean

@ConditionalOnExpression("#{"YES".equals(environment["test.auto.login.aop"])}")

public OrderTest orderTest4(){

OrderTest orderTest = new OrderTest();

System.out.println("当属性值等于YES时才会注入");

return orderTest;

}

比较高级是这个玩意支持SpEL表达式,换句话说就是能够让你支持更加复杂的逻辑判断

Resource Conditions

这种不经常使用,这里就不说了

Web Application Conditions

这种也不经常使用,这里也不说了

关于条件注解的用法就说到这里,为什么我们在条件注解中给出一些值,框架就能帮助我们自动判断是否需要注入呢。我们可以看下每个注解的实现

各种条件注解的实现

  • @ConditionalOnClass

@Target({ ElementType.TYPE, ElementType.METHOD })

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Conditional(OnClassCondition.class) // 关键在于这个

public @interface ConditionalOnClass

  • @ConditionalOnBean

@Target({ ElementType.TYPE, ElementType.METHOD })

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Conditional(OnBeanCondition.class)//关键也在这里

public @interface ConditionalOnBean

  • @ConditionalOnExpression

@Retention(RetentionPolicy.RUNTIME)

@Target({ ElementType.TYPE, ElementType.METHOD })

@Documented

@Conditional(OnExpressionCondition.class) //关键逻辑

public @interface ConditionalOnExpression

其他的就不列举了,通过这三个典型的注解,可以看到,真正让条件注解能够实现的就在于OnXxxx.class,下次再分析这个类都干了什么

以上是 springboot之@Conditional和@ConditionalXXX 的全部内容, 来源链接: utcz.com/z/515473.html

回到顶部