Spring Boot 条件注解@Conditional
条件注解决定自动配置类是否生效,是Spring Boot自动配置的核心机制。
@Conditional基础
接口定义
Java
@FunctionalInterface
public interface Condition {
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
基本使用
Java
@Configuration
@Conditional(MyCondition.class)
public class MyConfiguration {
// 只有MyCondition.matches()返回true时才加载
}
public class MyCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return context.getEnvironment().getProperty("my.feature.enabled", Boolean.class, false);
}
}
Spring Boot条件注解
类路径条件
Java
// 类路径存在指定类时生效
@ConditionalOnClass(DataSource.class)
public class DataSourceAutoConfiguration { }
// 类路径不存在指定类时生效
@ConditionalOnMissingClass("org.springframework.data.redis.core.RedisTemplate")
public class CacheAutoConfiguration { }
Bean条件
Java
// 容器中存在指定Bean时生效
@ConditionalOnBean(DataSource.class)
public class JdbcTemplateAutoConfiguration { }
// 容器中不存在指定Bean时生效
@ConditionalOnMissingBean
@Bean
public DataSource dataSource() { return new HikariDataSource(); }
// 指定Bean类型
@ConditionalOnMissingBean(name = "dataSource")
@Bean
public DataSource myDataSource() { }
属性条件
Java
// 配置属性满足条件时生效
@ConditionalOnProperty(prefix = "spring.datasource", name = "url")
public class DataSourceAutoConfiguration { }
// 指定属性值
@ConditionalOnProperty(prefix = "app.cache", name = "type", havingValue = "redis")
// 属性不存在时生效
@ConditionalOnProperty(prefix = "app.feature", name = "enabled", matchIfMissing = true)
资源条件
Java
// 类路径存在指定资源文件时生效
@ConditionalOnResource(resources = "classpath:db/schema.sql")
public class DatabaseInitializer { }
Web应用条件
Java
// Servlet Web应用时生效
@ConditionalOnWebApplication(type = Type.SERVLET)
public class WebMvcAutoConfiguration { }
// Reactive Web应用时生效
@ConditionalOnWebApplication(type = Type.REACTIVE)
public class WebFluxAutoConfiguration { }
// 非Web应用时生效
@ConditionalOnNotWebApplication
表达式条件
Java
// SpEL表达式为true时生效
@ConditionalOnExpression("${app.feature.enabled:false} and environment.acceptsProfiles('prod')")
public class ProdConfiguration { }
条件注解组合
Java
@Configuration
@ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class})
@ConditionalOnMissingBean(DataSource.class)
@ConditionalOnProperty(prefix = "spring.datasource", name = "url", matchIfMissing = true)
public class DataSourceAutoConfiguration {
@Bean
@ConditionalOnProperty(prefix = "spring.datasource", name = "type", havingValue = "hikari")
public DataSource dataSource() { }
}
自定义条件注解
Java
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Conditional(OnLinuxCondition.class)
public @interface ConditionalOnLinux {
}
public class OnLinuxCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return System.getProperty("os.name").toLowerCase().contains("linux");
}
}
// 使用
@Configuration
@ConditionalOnLinux
public class LinuxConfiguration { }
条件评估顺序
| 注解 | 评估时机 |
|---|---|
| @ConditionalOnClass | 类加载时(不触发类加载) |
| @ConditionalOnBean | Bean注册后 |
| @ConditionalOnProperty | 配置阶段 |
| @ConditionalOnWebApplication | 应用启动时 |
@ConditionalOnClass在类加载阶段评估,不会因类不存在而报错。
要点总结
- @Conditional是条件注解的基础接口
- @ConditionalOnClass检测类路径而非类加载
- @ConditionalOnBean检测容器中已注册的Bean
- @ConditionalOnProperty支持默认值matchIfMissing
- 多条件注解同时满足才生效
- 可自定义条件注解封装常用条件
📝 发现内容有误?点击此处直接编辑