Spring Boot中多个条件同时成立需用“且”逻辑,默认叠加@ConditionalOnXXX注解即AND关系;复杂逻辑用@ConditionalOnExpression写SpEL;Bean冲突时须配合@ConditionalOnMissingBean控制优先级。

要在Spring Boot中让多个条件同时成立才加载某个配置或Bean,必须明确组合逻辑是“且”还是“或”,直接叠加注解默认按“且”关系生效,但写错顺序或忽略隐含依赖会导致配置失效。
用多个@ConditionalOnXXX注解实现“且”关系
Spring Boot对同一目标(如一个@Configuration类或@Bean方法)上声明的多个条件注解,默认采用“全部满足”策略,即逻辑与(AND)。
第一步:在配置类上同时标注@ConditionalOnClass和@ConditionalOnProperty
@Configuration
@ConditionalOnClass(DataSource.class)
@ConditionalOnProperty(name = "app.datasource.enabled", havingValue = "true")
public class DataSourceConfig { ... }
这表示:仅当类路径存在DataSource类【且】application.yml中app.datasource.enabled=true时,该配置类才会被加载。
若只加了spring-boot-starter-jdbc但未配app.datasource.enabled=true,配置类不会生效——哪怕DataSource.class存在。
用@ConditionalOnExpression实现复杂布尔表达式
当需要“或”“非”“嵌套判断”等逻辑时,@ConditionalOnExpression是唯一能直接写SpEL表达式的注解。
方法一:用Ternary操作符表达“启用缓存或启用Redis”
@Configuration
@ConditionalOnExpression("#{${app.cache.enabled:false} || ${app.redis.enabled:false}}")
public class CacheSupportConfig { ... }
方法二:排除开发环境并要求JDBC驱动存在
@Bean
@ConditionalOnExpression("#{environment.getActiveProfiles()[0] != 'dev' && @classUtils.isPresent('javax.sql.DataSource')}")
public DataSource dataSource() { ... }
【注意】SpEL中调用静态方法必须用@符号前缀,如@classUtils.isPresent;直接写ClassUtils.isPresent会报错。
组合条件时避免Bean注册冲突
当多个自动配置类都试图注册同一个类型Bean(如DataSource),需用@ConditionalOnMissingBean控制优先级。
① 先定义基础数据源配置(无条件限制)
@Configuration
@ConditionalOnClass(DataSource.class)
public class DefaultDataSourceAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public DataSource defaultDataSource() { ... }
}
② 再定义高优先级定制配置(带额外条件)
@Configuration
@ConditionalOnClass(HikariDataSource.class)
@ConditionalOnProperty(name = "app.datasource.hikari", havingValue = "true")
public class HikariDataSourceAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public DataSource hikariDataSource() { ... }
}
只要HikariDataSource在类路径中且app.datasource.hikari=true,Hikari版本就会覆盖默认版本;否则走默认配置。
若两个配置都未加@ConditionalOnMissingBean,启动时会因Bean类型冲突报错。

















