在@Configuration bean 中的 SpEL 表达式中引用 ConfigurationProperties Beans

Mic*_*ons 5 java spring spring-el spring-boot

我有这个属性类:

import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties("some")
    public class SomeProperties {
        private List<String> stuff;

        public List<String> getStuff() {
            return stuff;
        }

        public void setStuff(List<String> stuff) {
            this.stuff = stuff;
        }    
    }
Run Code Online (Sandbox Code Playgroud)

我在 @Configuration 类中启用配置属性,如下所示:

import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableConfigurationProperties(SomeProperties.class)
public class SomeAutoConfiguration {    
}
Run Code Online (Sandbox Code Playgroud)

在同一个类(“SomeAutoConfiguration”)中,我想根据 SomeProperties 中的列表属性是否为空来创建另一个 bean。我想我可以将@ConditionalExpression 与以下 SpEl 一起使用:

@Bean
@ConditionalOnExpression("!(#someProperties.stuff?.isEmpty()?:true)")   
    public Object someBean(final SomeProperties someProperties) {
    return new Object();
}    
Run Code Online (Sandbox Code Playgroud)

SpEl 是正确的,但我无法获得包含我的属性的 bean。使用上面的表达式我遇到了

EL1007E:(pos 43): 在 null 上找不到属性或字段“东西”

并试图通过它的名字来获取豆子

@Bean
@ConditionalOnExpression("!(@'some.CONFIGURATION_PROPERTIES'.stuff?.isEmpty()?:true)")  
    public Object someBean(final SomeProperties someProperties) {
    return new Object();
} 
Run Code Online (Sandbox Code Playgroud)

结束于

NoSuchBeanDefinitionException:未定义名为“some.CONFIGURATION_PROPERTIES”的 bean

有任何想法吗?我已经尝试在另一个类中启用 ConfigurationProperties 但这也不起作用。

Bri*_*ice 5

为了补充 @PhilWebb 关于 Spring Boot 2+ 的答案,RelaxedPropertyResolver已被删除,以支持更强大的替代方案,名为Binder. 这是一个非常简单的例子:

@Configuration
@AutoConfigureBefore(JacksonAutoConfiguration.class)
@ConditionalOnMissingBean(ObjectMapper.class)
@Conditional(SpringJacksonPropertiesMissing.class)
public class ObjectMapperConfiguration {
    @Bean
    public ObjectMapper objectMapper() {
        return new ObjectMapper()
                .disable(FAIL_ON_UNKNOWN_PROPERTIES)
                .setSerializationInclusion(JsonInclude.Include.NON_NULL);
    }

    static class SpringJacksonPropertiesMissing extends SpringBootCondition {
        @Override
        public ConditionOutcome getMatchOutcome(ConditionContext context,
                                                AnnotatedTypeMetadata metadata) {
            return new ConditionOutcome(hasJacksonPropertiesDefined(context),
                                        "Spring Jackson property based configuration missing");
        }

        private boolean hasJackonPropertiesDefined(ConditionContext context) {
            return Binder.get(context.getEnvironment())
                         .bind(ConfigurationPropertyName.of("spring.jackson"),
                                                Bindable.of(Map.class))
                         .orElse(Collections.emptyMap())
                         .isEmpty();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

免责声明:此代码用于逐步淘汰有关 jackson 对象映射器的一些不良做法,以便将一些代码转换为spring boot 方式来配置对象映射器


Phi*_*ebb 4

我认为您面临的问题是@Conditions在解析类时进行评估@Configuration,因此不能保证SomePropertiesbean 已被定义。即使它已定义,您可能也不希望它提前初始化,因此我建议采用不同的方法。

您可以尝试@ConditionalOnPropety,这是 Spring Boot 有条件地想要基于属性启用自动配置时在内部使用的注释。如果这不够灵活,您可以创建自己的Condition并直接访问Environment以判断属性值是否为空。如果你想支持灵活绑定,你可以使用RelaxedPropertyResolver. 这是一个例子