从零到一:Spring Boot自定义条件注解的创建与使用

本文介绍了如何在Springboot中使用和自定义条件注解,如`@ConditionalOnProperty`的工作原理,以及如何通过继承`SpringBootCondition`或`Condition`接口创建自定义条件注解,以`@ConditionalOnSkill`为例,展示了如何根据配置文件中的技能值动态加载对应的Bean。
摘要由CSDN通过智能技术生成

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。

上篇文章介绍了Springboot有哪些条件注解及一些属性的含义,本篇文章将介绍一下如何自定义条件注解。

话不多说,上代码。

实践出真知

先分析Springboot提供的注解

在自定义条件之前,咱先看看Springboot条件注解是怎么实现的,就挑 @ConditionalOnProperty 注解看一下。
下图是@ConditionalOnProperty 注解的实现,从实现中可以看到除了元注解之外,它是被 @Conditional(OnPropertyCondition.class) 标记的,被@Conditional() 注解标记的注解表示该注解是个条件注解,@Conditional() 注解的value就对应值该注解的具体实现逻辑。下面我们就主要看看 OnPropertyCondition 类是怎么实现的。

接下来我们将进行实操。
ConditionalOnProperty注解

OnPropertyCondition 类继承了 SpringBootCondition 类,并重写了 getMatchOutcome() 方法,而 SpringBootCondition 类则是实现了 Condition接口并进行了封装,加入了类似日志之类的东西,感兴趣的可以细细看下,至此OnPropertyCondition 类就分析完了。

从上面的分析中我们可以发现,自定义条件注解主要分为两步:

  1. 自定义一个条件注解,该注解要被@Conditional() 注解标记。
  2. 写一个自定义条件注解的实现类。在实现时,有两个选择,一是继承 SpringBootCondition 类并重写 getMatchOutcome() 方法,二是实现 Condition接口并重写 matches() 方法。 SpringBootConditionCondition接口的实现并进行了封装,推荐使用SpringBootCondition ,当然,如果自定义条件注解的实现类已经有父类,使用 Condition接口也是没问题的。

其实还有一种选择那就是实现 ConfigurationCondition ,它继承了Condition接口,并在其基础上增加了一些针对配置类的条件判断方法,使用它也可以实现自定义条件注解,下篇文章将介绍一下 ConfigurationCondition接口及其和Condition接口的区别。

OnPropertyCondition 类

SpringBootCondition

OnPropertyCondition类图

实操

众所周知,某练习两年半的练习生技能包里有唱跳、Rap、打篮球三项技能,下面就以该练习生技能包为案例,激活什么技能就用什么技能。

侵删

  1. 自定义条件注解

新建一个技能条件注解 ConditionalOnSkill ,里面就一个value属性

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnSkillCondition.class)
public @interface ConditionalOnSkill {

    /**
     * 技能
     * @return
     */
    String value();
}
  1. 自定义条件注解实现类

新建一个 技能条件注解实现类OnSkillCondition ,该类中定义一个 PROPERTY_NAME 常量,该常量的值最终会从配置文件中读取。

public class OnSkillCondition extends SpringBootCondition {

    private static final String PROPERTY_NAME = "brother-rooster.skill";

    @Override
    public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //获取所有被自定义条件注解标记的填写的属性值
        Map<String, Object> attributes = metadata.getAnnotationAttributes(ConditionalOnSkill.class.getName());
        //获取常量值
        String value = attributes.get("value").toString();
        Environment environment = context.getEnvironment();
        //读取PROPERTY_NAME值
        String property = environment.getProperty(PROPERTY_NAME);

        ConditionMessage.Builder message = ConditionMessage.forCondition(ConditionalOnSkill.class);
        ConditionMessage conditionMessage = message.foundExactly(value);
        boolean match = value.equals(property);
        return new ConditionOutcome(match, conditionMessage);
    }
}
  1. 创建Bean接口及实现类

创建一个BrotherRoosterSkill接口,用于测试条件注解,然后分别创建3个实现类:篮球技能BrotherRoosterSkillBasketball、rap技能 BrotherRoosterRap、唱跳技能 BrotherRoosterSkillSing

public interface BrotherRoosterSkill {

    void printSkill();

}
public class BrotherRoosterSkillBasketball implements BrotherRoosterSkill {
    @Override
    public void printSkill() {
        System.out.println("打篮球");
    }
}
public class BrotherRoosterRap implements BrotherRoosterSkill {
    @Override
    public void printSkill() {
        System.out.println("rap");
    }
}
public class BrotherRoosterSkillSing implements BrotherRoosterSkill{
    @Override
    public void printSkill() {
        System.out.println("唱跳");
    }
}
  1. 新建配置注入技能包的Bean
    创建 ConditionConfig配置类 注入技能Bean
@Component
public class ConditionConfig {

    @Bean("brotherRoosterSkill")
    @ConditionalOnSkill("basketball")
    BrotherRoosterSkill brotherRoosterSkillBasketball(){
        System.out.println("打篮球技能激活。。。。。");
        return new BrotherRoosterSkillBasketball();
    }

    @Bean("brotherRoosterSkill")
    @ConditionalOnSkill("rap")
    BrotherRoosterSkill brotherRoosterSkillRap(){
        System.out.println("Rap技能激活。。。。。");
        return new BrotherRoosterRap();
    }

    @Bean("brotherRoosterSkill")
    @ConditionalOnSkill("sing")
    BrotherRoosterSkill brotherRoosterSkillSing(){
        System.out.println("唱跳技能激活。。。。。");
        return new BrotherRoosterSkillSing();
    }
}
  1. 测试

在配置文件中加入如下配置:

#kk技能包
brother-rooster.skill=sing

写一个单元测试类:

@SpringBootTest
public class ConditionalTest {

    @Resource
    private BrotherRoosterSkill brotherRoosterSkill;

    @Test
    public void testBrotherRoosterSkill(){
        System.out.println("鸡哥激活了哪个技能包:");
        brotherRoosterSkill.printSkill();
    }
}

启动测试,控制台打印结果如下图所示,可以看到 BrotherRoosterSkillSing被实例化了。


把配置改成 brother-rooster.skill=basketball , 控制台打印结果如下图所示,可以看到 BrotherRoosterSkillBasketball被实例化了。

至此,一个简单的Springboot自定义条件注解就搞定了。

  • 17
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

索码理

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值