SpringBoot根据条件自动装配Bean(基于Condition接口和Conditional注解)
程序员文章站
2024-02-15 11:52:17
...
在 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();
}
}
测试结果: