你好,我是柳岸花开。
在现代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源码 回复 222,获取Java面试题合集 关于我 一枚爱折腾的Java程序猿,专注Spring干货。把路上的问题记录下来,帮助那些和我一样的人。 好奇心强,喜欢并深入研究古天文。 崇尚 个人系统创建,做一些时间越长越有价值的事情。思考 把时间留下来 又 每刻都是新的。
本文由 mdnice 多平台发布