在 Spring 中添加新属性源的最佳方法是什么?

Gev*_*yan 4 configuration spring

我想添加一个新的属性源,可用于读取应用程序中的属性值。我想使用 Spring 来做到这一点。我在@Configuration 类中有一段这样的代码:

@Bean
public static PropertySourcesPlaceholderConfigurer placeHolderConfigurer() {        
    PropertySourcesPlaceholderConfigurer properties = new PropertySourcesPlaceholderConfigurer();
    MutablePropertySources sources = new MutablePropertySources();
    MyCustomPropertySource propertySource = new MyCustomPropertySource("my custom property source");
    sources.addFirst(propertySource);
    properties.setPropertySources(sources);
    return properties;
}
Run Code Online (Sandbox Code Playgroud)

这似乎工作得很好。但是,它也在做的是覆盖我不想覆盖的其他属性值(例如,spring boot 使用的 application.properties 文件中的 server.port 属性)。因此,基本问题是添加此属性源但不使其覆盖其他属性的最佳方法是什么。有什么方法可以获取现有的属性源并简单地添加它?

bob*_*sie 5

我通过向 Spring Boot 应用程序添加自定义初始化程序来实现此目的:

@SpringBootApplication
public class MyApp {

    public static void main(String[] args) {
        new SpringApplicationBuilder(MyApp.class)
            .initializers(new MyContextInitializer())  // <---- here
            .run(args);
    }

}
Run Code Online (Sandbox Code Playgroud)

其中MyContextInitializer包含: -

public class MyContextInitializer implements
    ApplicationContextInitializer<ConfigurableApplicationContext> {

    public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
        ConfigurableEnvironment environment = configurableApplicationContext.getEnvironment();

        // Create map for properites and add first (important)
        Map<String, Object> myProperties = new HashMap<>();
        myProperties.put("some-prop", "custom-value");
        environment.getPropertySources().addFirst(
            new MapPropertySource("my-props", myProperties));
    }

}
Run Code Online (Sandbox Code Playgroud)

请注意,如果您application.yaml包含: -

some-prop: some-value
another-prop: this is ${some-prop} property
Run Code Online (Sandbox Code Playgroud)

然后该initialize方法将更新some-propcustom-value,当应用程序加载时,它将在运行时具有以下值:

some-prop: custom-value
another-prop: this is custom-value property
Run Code Online (Sandbox Code Playgroud)

注意,如果该initialize方法做了一个简单的System.setProperty调用,即

    public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
        ConfigurableEnvironment environment = configurableApplicationContext.getEnvironment();
        System.setProperty("some-prop", "custom-value");
    }
Run Code Online (Sandbox Code Playgroud)

... 那么这another-prop将等于this is some-value propertywhich 不是我们通常想要的(并且我们失去了 Spring 配置属性解析的能力)。


Joc*_*ckX 0

一旦初始化,您也许可以将 propertySource 直接添加到环境中。

编辑:由于这是在处理类之后完成的,因此您不能期望注释从同一类中的此特定 PropertySource 或之前加载的任何其他属性中@Value获取任何内容。@Configuration

@Configuration
public class YourPropertyConfigClass{

    @Value("${fromCustomSource}")
    String prop; // failing - property source not yet existing

    @Autowired
    ConfigurableEnvironment env;

    @PostConstruct
    public void init() throws Exception {
        env.getPropertySources().addFirst(
             new MyCustomPropertySource("my custom property source"));
    }
}

@Configuration
@DependsOn("YourPropertyConfigClass")
public class PropertyUser {

    @Value("${fromCustomSource}")
    String prop; // not failing
}
Run Code Online (Sandbox Code Playgroud)

您可以将 移动@PostConstruct到一个单独的@Configuration类并使用这些属性标记其他类@DependOn("YourPropertyConfigClass")(这可行 - 但也许有更好的方法来强制配置顺序?)。

MyCustomPropertySource无论如何 - 如果不能简单地使用注释添加-这只是值得的@PropertySource("file.properties")- 这将解决简单属性文件的问题。