PropertySourcesPlaceholderConfigurer未在SpringBoot项目中向Environment注册

nod*_*e42 7 groovy spring spring-boot

我正在将一个工作项目从使用SpringBoot命令行参数移动到从文件中读取属性.以下是该@Configuration课程的相关部分:

@Configuration
class RemoteCommunication {

    @Inject
    StandardServletEnvironment env


    @Bean
    static PropertySourcesPlaceholderConfigurer placeholderConfigurer () {
        // VERIFIED this is executing...
        PropertySourcesPlaceholderConfigurer target = new PropertySourcesPlaceholderConfigurer()
        // VERIFIED this files exists, is readable, is a valid properties file
        target.setLocation (new FileSystemResource ('/Users/me/Desktop/mess.properties'))
        // A Debugger does NOT show this property source in the inject Environment
        target
    }


    @Bean  // There are many of these for different services, only one shown here.
    MedicalSorIdService medicalSorIdService () {
        serviceInstantiator (MedicalSorIdService_EpicSoap, 'uri.sor.id.lookup.internal')
    }


    // HELPER METHODS...


    private <T> T serviceInstantiator (final Class<T> classToInstantiate, final String propertyKeyPrimary) {
        def value = retrieveSpringPropertyFromConfigurationParameter (propertyKeyPrimary)
        classToInstantiate.newInstance (value)
    }


    private def retrieveSpringPropertyFromConfigurationParameter (String propertyKeyPrimary) {
        // PROBLEM: the property is not found in the Environment
        def value = env.getProperty (propertyKeyPrimary, '')
        if (value.isEmpty ()) throw new IllegalStateException ('Missing configuration parameter: ' + "\"$propertyKeyPrimary\"")
        value
    }
Run Code Online (Sandbox Code Playgroud)

使用@Value注入属性确实有效,但是Environment如果可能的话,我宁愿直接使用它.如果设置不在Environment那时我不确定@Value从哪里拉它们......

env.getProperty() 当我传入指定属性的命令行参数时,继续运行良好.

欢迎任何建议!

Sot*_*lis 16

这里的问题是PropertySourcesPlaceholderConfigurerStandardServletEnvironment,或Environment简单的区别.

Environment是一个支持整体的对象,ApplicationContext可以解析一堆属性(Environment接口扩展PropertyResolver).A ConfigurableEnvironment有一个MutablePropertySources可以检索的对象getPropertySources().这MutablePropertySources包含一个被检查LinkedListPropertySource对象,以便解析所请求的属性.

PropertySourcesPlaceholderConfigurer是一个具有自己状态的独立对象.它拥有自己的MutablePropertySources对象来解析属性占位符.PropertySourcesPlaceholderConfigurer实现EnvironmentAware所以当ApplicationContext获取它时,它给它它的Environment对象.在PropertySourcesPlaceholderConfigurer添加此EnvironmentMutablePropertySources它自己的.然后,它还会将Resource您指定的各种对象添加setLocation()为附加属性.这些Resource对象不会添加到Environments中MutablePropertySources,因此无法使用env.getProperty(String).

所以你不能直接将属性加载PropertySourcesPlaceholderConfigurerEnvironment.你可以做的是直接添加到Environment's MutablePropertySouces.一种方法是

@PostConstruct
public void setup() throws IOException {
    Resource resource = new FileSystemResource("spring.properties"); // your file
    Properties result = new Properties();
    PropertiesLoaderUtils.fillProperties(result, resource);
    env.getPropertySources().addLast(new PropertiesPropertySource("custom", result));
}
Run Code Online (Sandbox Code Playgroud)

或者干脆(感谢@ M.Deinum)

@PostConstruct
public void setup() throws IOException {
    env.getPropertySources().addLast(new ResourcePropertySource("custom", "file:spring.properties")); // the name 'custom' can come from anywhere
}
Run Code Online (Sandbox Code Playgroud)

请注意,添加a @PropertySource具有相同的效果,即.直接添加到Environment,但你是静态而不是动态地做.

  • 小提示,还有一个 `ResourcePropertySource`,它只需要一个 `Resource` 或位置 `String`。为您节省几行自己阅读属性的时间。即`env.getPropertySources().addLast(new ResourcePropertySource("custom", "file:spring.properties"));` 将产生相同的结果,代码更少。 (2认同)

Jak*_*ski 5

在 SpringBoot 中使用@EnableConfigurationProperties注解就足够了——你不需要设置PropertySourcesPlaceholderConfigurer.

然后在 POJO 上添加注解 @ConfigurationProperties,Spring 会自动注入 application.properties 中定义的属性。

您也可以使用 YAML 文件 - 您只需要向类路径添加适当的依赖项(如 SnakeYaml)

你可以在这里找到详细的例子:http : //spring.io/blog/2013/10/30/empowering-your-apps-with-spring-boot-s-property-support