SpringBoot自定义Condition注解实战 - 第402篇
在前面的文章中《Spring Boot条件注解》,我们了解到了Spring Boot给我们提供了很多的条件注解,但是并不能满足所有的场景。
有这么一种需求可能就满足不了了:需要同一套代码适配个版本数据库(数据库不同,且部分表的字段及关联关系可能会不同)。
实现的关键点是对bean的实例化添加一个条件判断来控制。其实SpringBoot里面新增了很多条件注解,能实现这个功能。但是都有些局限性,最终是采用自定义条件注解的方案。
一、SpringBoot自带的注解ConditionalOnProperty
这个注解不做过多的解释,只说通过这个注解怎么实现我们的功能。
假设我们application.properties中配置一个配置项为:
- #bean实例化条件配置项
- conditionKey=1.0
那么只需要加上@ConditionalOnProperty的name和havingValue就能实现,只有配置文件中name对应的配置项的值和havingValue内容一致才实例化这个对象。
针对我们上面配置的application.properties的内容,@ConditionalOnProperty的使用案例如下面代码所示:
- @Component
- @ConditionalOnProperty(name="conditionKey" ,havingValue = "1.0")
- public class DAOAdapterImpl implements DAOAdapter{
-
- public void save(){
- System.out.println("我是实现类01");
- }
-
- }
这个注解的局限性:这个注解的havingValue里面只能配置一个值。
由于项目个性化需求,希望这个havingValue可以配置多个值,name对应的配置项的Value只要满足havingValue里面多个值的就表示匹配正确。即,havingValue里面可以配置多个值,name对应配置项的值来和havingValue匹配时,采用逻辑或匹配,满足一个值就算匹配正确。
二、自定义条件注解
2.1 思路
注解里面有2个属性,具体如下:
(1)name:String类型,用来接受application.properties的配置项的key
(2)havingValue:String数组类型,用来和name对应key的Value进行匹配
2.2 定义注解
我们自定义注解:
- import org.springframework.context.annotation.Conditional;
- import java.lang.annotation.*;
-
- /**
- * 自定义条件注解
- *
- * @author 悟纤「公众号SpringBoot」
- * @date 2021-10-12
- * @slogan 大道至简 悟在天成
- */
-
- @Retention(RetentionPolicy.RUNTIME)
- @Target({ElementType.TYPE, ElementType.METHOD})
- @Documented
- @Conditional(CustomOnPropertyCondition.class)
- public @interface CustomConditionalOnProperty {
- /**
- * 条件变量的name
- */
- String name() default "";
- /**
- * havingValue数组,支持or匹配
- */
- String[] havingValue() default {};
- }
2.3 定义注解的匹配规则
重点的实现就是匹配规则:
- import org.springframework.context.annotation.Condition;
- import org.springframework.context.annotation.ConditionContext;
- import org.springframework.core.type.AnnotatedTypeMetadata;
- import java.util.Map;
-
- /**
- * 自定义条件注解的验证规则
- *
- * @author 悟纤「公众号SpringBoot」
- * @date 2021-10-12
- * @slogan 大道至简 悟在天成
- */
- public class CustomOnPropertyCondition implements Condition {
- @Override
- public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
- //获取注解上配置的信息
- Map<String, Object> annotationAttributes = metadata.getAnnotationAttributes(CustomConditionalOnProperty.class.getName());
- String propertyName = (String)annotationAttributes.get("name");
- String[] values = (String[]) annotationAttributes.get("havingValue");
- if (0 == values.length) {
- return false;
- }
-
- //获取环境中的配置的信息(这里也就是application.properties的信息)
- String propertyValue = context.getEnvironment().getProperty(propertyName);
- // 有一个匹配上就ok
- if(propertyValue != null){
- for (String havingValue : values) {
- if (havingValue.equalsIgnoreCase(propertyValue)) {
- return true;
- }
- }
- }
-
-
- return false;
- }
- }
2.4 使用
使用起来是很简单的,如下示例:
@CustomConditionalOnProperty(name="conditionKey" ,havingValue = {"1.0","3.0"})
三、小结
自定义Condition注解,主要就2步:
(1)定义一个条件注解
(2)定义一个条件的校验规则
购买完整视频,请前往:http://www.mark-to-win.com/TeacherV2.html?id=287