Springboot如何自定义条件注解

你好,我是柳岸花开。

在现代Java开发中,Spring框架提供了丰富的注解功能,使得配置和管理Bean变得异常简单和灵活。其中,条件化注解(Conditional Annotations)是一个强大的工具,它允许我们根据特定条件有选择地创建或启用Spring Bean。在本文中,我们将首先介绍ConditionalOnProperty注解,然后通过实际场景引出和分析如何自定义一个条件注解ConditionalOnMissingProperty

什么是ConditionalOnProperty

ConditionalOnProperty是Spring Boot中常用的一个条件注解,它允许我们根据配置文件中的属性值来控制Bean的创建。如果配置文件中存在指定的属性,并且其值符合条件,则创建相应的Bean;否则,不创建。

示例场景

假设我们有一个邮件服务MailService,我们希望仅在配置文件中启用了邮件功能时才创建这个Bean:

@Configuration
public class MailConfiguration {

    @Bean
    @ConditionalOnProperty(name = "mail.enabled", havingValue = "true")
    public MailService mailService() {
        return new MailService();
    }
}

在配置文件application.properties中,我们可以这样配置:

mail.enabled=true

mail.enabled的值为true时,MailService Bean将被创建。否则,不会创建。

ConditionalOnProperty到自定义注解ConditionalOnMissingProperty

虽然ConditionalOnProperty非常强大,但有时我们需要更加灵活的条件判断。例如,我们希望在配置文件中缺少某个属性时才创建Bean。为此,我们可以自定义一个条件注解ConditionalOnMissingProperty

自定义注解ConditionalOnMissingProperty

首先,我们定义一个自定义注解ConditionalOnMissingProperty

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Conditional;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Conditional({OnMissingPropertyCondition.class})
@Target(
{ElementType.TYPE, ElementType.METHOD})
public @interface ConditionalOnMissingProperty {
    String[] value();

    String prefix();

    String name();
}

条件类OnMissingPropertyCondition

接下来,我们实现条件逻辑类OnMissingPropertyCondition

import java.util.Arrays;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.condition.ConditionMessage;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class OnMissingPropertyCondition extends SpringBootCondition {
    public OnMissingPropertyCondition() {
    }

    public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
        String prefix = (String)metadata.getAnnotationAttributes(ConditionalOnMissingProperty.class.getName()).get("prefix");
        String name = (String)metadata.getAnnotationAttributes(ConditionalOnMissingProperty.class.getName()).get("name");
        String[] values = (String[])((String[])metadata.getAnnotationAttributes(ConditionalOnMissingProperty.class.getName()).get("value"));
        String property = "";
        if (StringUtils.isNotBlank(prefix)) {
            property = property + prefix;
            if (StringUtils.isNotBlank(name)) {
                property = property + "." + name;
            }
        } else if (StringUtils.isNotBlank(name)) {
            property = property + name;
        }

        if (StringUtils.isBlank(property)) {
            return ConditionOutcome.noMatch(ConditionMessage.of("missing ConditionalOnMissingProperty"new Object[0]));
        } else {
            String value = context.getEnvironment().getProperty(property);
            return Arrays.asList(values).contains(value) ? ConditionOutcome.noMatch(ConditionMessage.of("missing property=" + Arrays.toString(values), new Object[0])) : ConditionOutcome.match(ConditionMessage.of("missing property=" + Arrays.toString(values), new Object[0]));
        }
    }
}

条件逻辑说明

  • getMatchOutcome:实现了具体的条件逻辑。根据配置文件中的属性值,决定是否创建Bean。
  • buildPropertyName:辅助方法,用于构建完整的属性名称。

实际应用

假设我们希望仅在配置文件中缺少某个属性时才创建一个服务MyService,我们可以这样使用ConditionalOnMissingProperty注解:

@ConditionalOnMissingProperty(prefix = "app", name = "feature.enabled", value = {"true"})
@Bean
public MyService myService() {
    return new MyService();
}

在这个例子中,如果app.feature.enabled的值为true,则myService Bean将不会被创建。否则,将创建myService Bean。

总结

通过本文的讲解,我们从Spring的ConditionalOnProperty注解出发,逐步深入到自定义条件注解ConditionalOnMissingProperty的实现和应用。条件注解使得我们的Spring应用程序更加灵活和可配置,极大地增强了代码的可维护性和可扩展性。

希望通过这篇文章,大家能够更好地理解和应用自定义条件注解,提升Spring应用的开发效率和质量。如果你有任何问题或建议,欢迎在评论区留言讨论!

👇关注我,下期了解👇 ​ SpringMVC源码 ​ ​ alt ​ ​ 回复 222,获取Java面试题合集 ​ 关于我 ​ 一枚爱折腾的Java程序猿,专注Spring干货。把路上的问题记录下来,帮助那些和我一样的人。 ​ 好奇心强,喜欢并深入研究古天文。 ​ 崇尚 个人系统创建,做一些时间越长越有价值的事情。思考 把时间留下来 又 每刻都是新的。

本文由 mdnice 多平台发布

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值