天天看点

SpringBoot根据条件自动装配Bean(基于Condition接口和Conditional注解)

    在

SpringBoot

中,我们经常可以看到很多以

Condition

开头的注解,例如:

ConditionalOnBean

ConditionalOnMissingBean

ConditionalOnClass

ConditionalOnMissingClass

ConditionalOnJava

ConditionalOnProperty

ConditionalOnResource

等等,如果看它们的源码的话,可以发现它们都使用了

@Conditional

注解,并且指定了一个或者多个

XxxCondition.class

,再看

XxxCondition

源码,发现它们都实现了

Condition

接口。

Condition

接口和

Conditional

注解是

SpringBoot

提供的实现按条件自动装配

Bean

的工具。

如何使用 Condition 接口和 Conditional 注解

  • Condition

    接口源码如下,自定义条件时实现该接口
/**
 * 实现 Condition 的 matches 方法,在此方法中进行逻辑判断
 * 方法返回值:
         * true:装载此类到 Spring 容器中
         * false:不装载此类到 Spring 容器中
 */
public interface Condition {
    boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
           
  • Conditional

    注解源码如下

    使用方式:

    在配置类(带有

    @SpringBootConfiguration

    或者

    @Configuration

    的类)上加此注解或者在有

    @Bean

    的方法上加此注解,并指定实现了

    Condition

    接口的

    Class

    对象,注意:如果指定多个

    Class

    对象,当且仅当所有

    Class

    matches

    方法都返回

    true

    时,才会装载

    Bean

    Spring

    中。

    使用范例:

    @Conditional(GBKCondition.class)

    @Conditional({GBKCondition.class, UTF8Condition.class})

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
    /**
     * value:Class 对象数组,当配置多个 Class 对象时,当且仅当所有条件都返回 true 时,相关的 Bean 才可以被装载到 Spring 容器中
     */
    Class<? extends Condition>[] value();
}
           

案例

    以系统字符集判断系统加载

GBK

还是

UTF-8

的类

// 面向接口编程思想:编码转换接口
public interface EncodingConvert {
}
// UTF8 编码
public class UTF8EncodingConvert implements EncodingConvert {
}
// GBK 编码
public class GBKEncodingConvert implements EncodingConvert {
}
// GBK 加载条件,实现 Condition 接口,获取程序运行时参数,判断是否是加载该 Bean
public class GBKCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        String encoding = System.getProperty("file.encoding");
        return null != encoding ? ("GBK".equals(encoding.toUpperCase())) : false;
    }
}
// UTF-8 加载条件
public class UTF8Condition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        String encoding = System.getProperty("file.encoding");
        return null != encoding ? ("UTF-8".equals(encoding.toUpperCase())) : false;
    }
}
// 编码配置类
@SpringBootConfiguration
// @Conditional(value = { UTF8Condition.class, GBKCondition.class })
public class EncodingConvertConfiguration {
    @Bean
    @Conditional(GBKCondition.class)
    public EncodingConvert gbkEncoding() {
        return new GBKEncodingConvert();
    }
    @Bean
    @Conditional(value = UTF8Condition.class)
    public EncodingConvert utf8Encoding() {
        return new UTF8EncodingConvert();
    }
}
// 启动类
@SpringBootApplication
public class App {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(App.class, args);
        System.out.println(context.getBeansOfType(EncodingConvert.class));
        context.close();
    }
}
           

测试结果:

SpringBoot根据条件自动装配Bean(基于Condition接口和Conditional注解)
SpringBoot根据条件自动装配Bean(基于Condition接口和Conditional注解)

继续阅读