PropertySourcesPlaceholderConfigurer不在SpringBoot项目中注册到Environment [英] PropertySourcesPlaceholderConfigurer not registering with Environment in a SpringBoot Project

查看:749
本文介绍了PropertySourcesPlaceholderConfigurer不在SpringBoot项目中注册到Environment的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  @Configuration 
class RemoteCommunication {

@Inject
StandardServletEnvironment env

$ b @Bean
static PropertySourcesPlaceholderConfigurer placeholderConfigurer(){
// VERIFIED this is executed ...
PropertySourcesPlaceholderConfigurer target = new PropertySourcesPlaceholderConfigurer()
// VERIFIED这个文件存在,可读,是一个有效的属性文件
target.setLocation(new FileSystemResource ('/Users/me/Desktop/mess.properties'))
//一个调试器在注入环境中不显示这个属性源
target
}


@Bean //对于不同的服务有很多种,这里只显示一个。
MedicalSorIdService medicalSorIdService(){
serviceInstantiator(MedicalSorIdService_EpicSoap,'uri.sor.id.lookup.internal')
}


//帮助者方法...


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


private def retrieveSpringPropertyFromConfigurationParameter(String propertyKeyPrimary){
// PROBLEM:在环境中找不到该属性
def value = env.getProperty(propertyKeyPrimary,'')
if(value .isEmpty())抛出新的IllegalStateException('Missing配置参数:'+\$ propertyKeyPrimary \)
value
}

使用 @Value 注入属性属性,但是我会而是尽可能直接使用 Environment >。如果这些设置不在 Environment 中,那么我不太确定 @Value 是从哪里拉出来的......

env.getProperty()当我传递指定属性的命令行参数时继续工作。



欢迎提供任何建议! PropertySourcesPlaceholderConfigurer StandardServletEnvironment Environment 之间。
$ b

Environment 是一个支持整个 ApplicationContext 并且可以解析一堆属性( Environment interface extends PropertyResolver )。一个 ConfigurableEnvironment 有一个 MutablePropertySources 对象,您可以通过 getPropertySources()。这 MutablePropertySources 包含 PropertySource 被检查对象的 LinkedList 以解析所请求的属性。



PropertySourcesPlaceholderConfigurer 是一个独立的对象,具有自己的状态。它拥有自己的 MutablePropertySources 对象来解析属性占位符。 PropertySourcesPlaceholderConfigurer implements EnvironmentAware 所以当 ApplicationContext 得到它时,它给它它的 Environment 对象。 PropertySourcesPlaceholderConfigurer 将此 Environment MutablePropertySources 添加到它自己的。然后它还会将您用 setLocation()指定的各种对象添加为其他属性。 这些资源对象不会被添加到 Environment 的 MutablePropertySources ,因此不可用于 env.getProperty(String)



因此,您无法直接将 PropertySourcesPlaceholderConfigurer 加载的属性放入 Environment 中。你可以直接添加到 Environment MutablePropertySouces 中。一种方法是使用

  @PostConstruct 
public void setup()throws IOException {
Resource resource = new的FileSystemResource( spring.properties); //你的文件
属性result = new Properties();
PropertiesLoaderUtils.fillProperties(result,resource);
env.getPropertySources()。addLast(new PropertiesPropertySource(custom,result));

$ / code>

或简单地(谢谢@ M.Deinum)

  @PostConstruct $ b $ public void set()throws IOException {
env.getPropertySources()。addLast(new ResourcePropertySource(custom, 文件:spring.properties)); //名称'custom'可以来自任何地方
}

请注意, code> @PropertySource 具有相同的效果,即。直接添加到 Environment 中,但是您正在静态而不是动态地添加。


I am moving a working project from using SpringBoot command line arguments to reading properties from a file. Here are the involved portions of the @Configuration class:

@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
    }

Using @Value to inject the properties does work, however I'd rather work with the Environment directly if at all possible. If the settings are not in the Environment then I am not exactly sure where @Value is pulling them from...

env.getProperty() continues to work well when I pass in command line arguments specifying the properties though.

Any suggestions are welcome!

解决方案

The issue here is the distinction between PropertySourcesPlaceholderConfigurer and StandardServletEnvironment, or Environment for simplicity.

The Environment is an object that backs the whole ApplicationContext and can resolve a bunch of properties (the Environment interface extends PropertyResolver). A ConfigurableEnvironment has a MutablePropertySources object which you can retrieve through getPropertySources(). This MutablePropertySources holds a LinkedList of PropertySource objects which are checked in order to resolve a requested property.

PropertySourcesPlaceholderConfigurer is a separate object with its own state. It holds its own MutablePropertySources object for resolving property placeholders. PropertySourcesPlaceholderConfigurer implements EnvironmentAware so when the ApplicationContext gets hold of it, it gives it its Environment object. The PropertySourcesPlaceholderConfigurer adds this Environment's MutablePropertySources to its own. It then also adds the various Resource objects you specified with setLocation() as additional properties. These Resource objects are not added to the Environment's MutablePropertySources and therefore aren't available with env.getProperty(String).

So you cannot get the properties loaded by the PropertySourcesPlaceholderConfigurer into the Environment directly. What you can do instead is add directly to the Environment's MutablePropertySouces. One way is with

@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));
}

or simply (thanks @M.Deinum)

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

Note that adding a @PropertySource has the same effect, ie. adding directly to the Environment, but you're doing it statically rather than dynamically.

这篇关于PropertySourcesPlaceholderConfigurer不在SpringBoot项目中注册到Environment的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆