我想基于属性文件中的枚举加载@Configuration
类,所以我有以下类:
@Configuration
@ConditionalOnExpression("#{ ${demo.spel.demo-enum} eq T(demo.spel.DemoEnum).VALUE }")
public class DemoConfig {}
我有:demo.spel.demo-enum=value
中的application.properties
这不起作用,并引发异常:
由以下原因导致:org.springframework.expression.spel.SpelEvaluationException:EL1008E:在类型为“ org.springframework.beans.factory.config.BeanExpressionContext”的对象上找不到属性或字段“值”-可能不是公共的,也可能不是有效吗?
奇怪的是,如果我在表达式的属性部分添加单引号,在表达式的枚举部分添加toString()
,则没有例外,条件为true,并且创建了bean(通过在调试日志记录中检查控制台输出进行验证):
@ConditionalOnExpression("#{ '${demo.spel.demo-enum}' eq T(demo.spel.DemoEnum).VALUE.toString() }")
问题:
为什么比较这样的枚举失败? Spring如何成功地转换值并以字符串而不是类型进行比较?
这是在Spring Boot 2.0.4上
答案 0 :(得分:2)
这应该很明显。
考虑以下Java代码:
foo.equals(DemoEnum.VALUE)
这将需要一个对象foo
,可能是this
上的一个字段:
this.foo.equals(DemoEnum.VALUE)
如果属性占位符的计算结果为“ foo”,则第一个SpEL表达式等于
#this.foo eq T(DemoEnum).VALUE
因此SpEL在foo
上寻找属性#this
编辑
如果您创建班级:
public class Foo {
@Value("${some.property}")
private DemoEnum enum;
public getEnum() {
return this.enum;
}
}
然后将一个bean添加到名为“ foo”的上下文中,然后您就可以使用
foo.enum eq ...
由于#this
是BeanExpressionContext
,允许您引用其他bean。
答案 1 :(得分:0)
我有类似的问题。
我有一个功能,默认情况下已启用。要禁用它,应用程序配置文件应显式禁用它。 demo.feature.disable:true
我有一个以此属性为条件的spring bean(默认情况下启用)。
@ConditionalOnExpression("#{ ${demo.feature.disable} != true }")
@Component
public class FeatureModule {
}
问题是,当未在配置文件-demo.spel.value
中定义application.yml
时,此组件的初始化将因
Caused by: org.springframework.expression.spel.SpelParseException: EL1041E: After parsing a valid expression, there is still more data in the expression: 'lcurly({)'
为解决此问题,我提供了默认值。
@ConditionalOnExpression("#{ ${demo.feature.disable:false} != true }")
@Component
public class FeatureModule {
}
现在,当我对其进行测试时。 默认情况下,此组件已初始化。
如果配置文件中没有demo.feature.disable
,则将初始化此组件。
如果配置文件中有demo.feature.disable:true
,则不会初始化此组件。
如果配置文件中有demo.feature.disable:false
,则此组件将被初始化。