欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-02-15 11:52:17
...

    在 SpringBoot 中,我们经常可以看到很多以 Condition 开头的注解,例如:ConditionalOnBeanConditionalOnMissingBeanConditionalOnClassConditionalOnMissingClassConditionalOnJavaConditionalOnPropertyConditionalOnResource等等,如果看它们的源码的话,可以发现它们都使用了@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对象,当且仅当所有Classmatches方法都返回true时,才会装载BeanSpring中。
    使用范例:
    @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注解)