在Spring Boot中,@ConditionalOnExpression需用#{...}包裹SpEL表达式,如#{systemProperties['os.name'].toLowerCase().contains('win')};须处理空值(用?:或!=null);environment必须小写;多条件需逻辑运算且前置判空。

在Spring Boot中,当需要根据SpEL表达式动态控制某个Bean是否注册到IoC容器时,必须正确书写@ConditionalOnExpression注解,否则启动会报错或条件失效。
基础写法:单个布尔表达式
直接传入一个返回boolean的SpEL表达式字符串,用双引号包裹,整个表达式必须被#{...}包围。
@ConditionalOnExpression("#{systemProperties['os.name'].toLowerCase().contains('win')}"
这行代码会在Windows系统下才加载被标注的Bean。注意systemProperties是Spring内置的上下文对象,无需手动注入。
带默认值的写法:避免空指针
访问配置项时,如果配置未定义,SpEL会抛EvaluationException导致启动失败。必须用?:提供默认值。
方法一:使用?:安全判空
@ConditionalOnExpression("#{environment.getProperty('app.feature.enabled', 'false') == 'true'}"
方法二:更稳妥地结合!= null判断
@ConditionalOnExpression("#{environment.getProperty('app.mode') != null && environment.getProperty('app.mode').equals('debug')}"
【environment必须小写】——Spring上下文里固定为environment,写成Environment或env会解析失败。
组合多个条件
第一步:用逻辑运算符连接多个子表达式
#{systemEnvironment['USER'] == 'admin' && systemProperties['java.version'].startsWith('17')}
第二步:确保所有引用对象都存在,比如systemEnvironment在Docker容器中可能为空,此时需前置判空
#{systemEnvironment != null && systemEnvironment['USER'] == 'admin'}
第三步:复杂逻辑建议抽成工具类+@Conditional自定义条件,避免SpEL过长难以维护