简体   繁体   English

以编程方式创建的Spring Boot上下文未设置类型安全的配置属性

[英]Spring Boot context created programmatically does not set typesafe configuration properties

We're moving our huge application to Spring Boot at the moment which works very well for our production code. 目前,我们正在将庞大的应用程序移至Spring Boot,这对于我们的生产代码非常有效。 Unfortunately we also have to adapt all tests. 不幸的是,我们还必须适应所有测试。 We want to keep changes as little as possible here for now and try to only rewrite the one big factory class nearly every test uses to create instances of common classes. 我们现在想要在这里尽可能少地进行更改,并尝试仅重写几乎每个测试用于创建公共类实例的一个大工厂类。 Because objects are created by method call we are forced to create a context programmatically. 由于对象是通过方法调用创建的,因此我们不得不以编程方式创建上下文。 We've managed it to get insertion of properties to fields annotated with @Value working, but it does not work for the new way Spring Boot introduces ( typesafe configuration properties ). 我们已经对其进行了管理,以将属性插入到使用@Value进行注释的字段中,但是不适用于Spring Boot引入的新方式( typesafe配置属性 )。

Here a little example which illustrates the problem: 这是一个说明问题的小例子:

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
PropertySourcesPlaceholderConfigurer propertiesPostProcessor = new PropertySourcesPlaceholderConfigurer();
ropertiesPostProcessor.setLocation(new ClassPathResource("config/test.properties"));
context.addBeanFactoryPostProcessor(propertiesPostProcessor);
context.register(PropertyTest.class);
context.refresh();

PropertyTest bean = context.getBean(PropertyTest.class);
System.out.println("value="+bean.getValue());
System.out.println("valueTypesafe="+bean.getValueTypesafe());

PropertyTest class: PropertyTest类:

@Configuration
@ConfigurationProperties(prefix = "test")
@EnableConfigurationProperties
public class PropertyTest {
    @Value("${test.value}")
    private String value;

    private String valueTypesafe;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public String getValueTypesafe() {
        return valueTypesafe;
    }

    public void setValueTypesafe(String valueTypesafe) {
        this.valueTypesafe = valueTypesafe;
    }
}

test.properties test.properties

test.value="works"
test.valueTypesafe="works"
valueTypesafe="works"

output: 输出:

value="works"
valueTypesafe=null

We've also tried several variations of this (other annotations, contexts, etc.), but nothing worked. 我们还尝试了这种方法的多种变体(其他注释,上下文等),但没有任何效果。 I've tried to find out how Spring Boot does it, but ended up in EnableConfigurationPropertiesImportSelector and ConfigurationPropertiesBindingPostProcessor , where we did not managed it to integrate them into our context. 我试图找出Spring Boot是如何做到的,但最终出现在EnableConfigurationPropertiesImportSelectorConfigurationPropertiesBindingPostProcessor中 ,我们没有对其进行管理以将它们集成到上下文中。


Solution

We've finally managed it by touching every test and adding @SpringApplicationConfiguration . 我们终于通过触摸每个测试并添加@SpringApplicationConfiguration@SpringApplicationConfiguration Thus not creating the context manually. 因此,不是手动创建上下文。 The programmatically way did not work and would have had other disadvantages as well. 以编程的方式行不通,并且还会有其他缺点。

Short answer is that you're not using Spring Boot. 简短的答案是您没有使用Spring Boot。 If you want to use those features, you need to let Spring Boot create the context of your application for you. 如果要使用这些功能,则需要让Spring Boot为您创建应用程序的上下文。 Check SpringApplication and SpringApplicationBuilder . 检查SpringApplicationSpringApplicationBuilder In test scenario, check SpringApplicationConfiguration . 在测试场景中,检查SpringApplicationConfiguration

@ConfigurationProperties annotated POJO are processed against the Environment and your code above does not initialize it properly. @ConfigurationProperties注释的POJO是针对Environment处理的,上面的代码未正确初始化它。 You may want to have a look at EnvironmentTestUtils and how it's used in the Spring Boot test suite. 您可能想看看EnvironmentTestUtils及其在Spring Boot测试套件中的用法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM