从application.yml读取属性时,将忽略Spring配置文件 [英] Spring profile is ignored when reading properties from application.yml

查看:1616
本文介绍了从application.yml读取属性时,将忽略Spring配置文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有扫描Spring上下文的代码:

I have this code that scans Spring context:

public void scan() {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();

    context.register(SomeConfig.class);
    context.refresh();
}

我需要从 application.yml读取属性文件,所以在 SomeConfig 类中,我有这个:

I need properties to be read from application.yml file, so in SomeConfig class, I have this:

@Configuration
@PropertySource(value = "classpath:application.yml", factory = YamlPropertyLoaderFactory.class)
public class SomeConfig {
  //some beans
}

(我从这里

application.yml 是一个典型的Spring Boot文件通过个人资料和默认个人资料:

application.yml is a typical Spring Boot file with some properties by profile, and a default profile:

spring:
  profiles:
    active: p1

---

spring:
   profiles: p1

file: file1.txt

---

spring:
   profiles: p2

file: file2.txt

在某些bean中,我正在使用 @Value 读取 file 属性。

In some bean, I'm reading file property using @Value.

当我运行我的应用程序时,我传递 -Dspring.profiles.active = p1 变量,但是我收到错误:

When I run my application, I'm passing -Dspring.profiles.active=p1 variable, but I'm getting an error:


无法解析值$ {file}中的占位符'file'

Could not resolve placeholder 'file' in value "${file}"

(即使我没有传递任何个人资料也应该有效,因为application.yml的默认配置文件设置为p1)

(It should work even if I don't pass any profile since application.yml has default profile set to p1)

如果我从 application.yml 中删除​​所有配置文件配置,它可以正常工作:

If I remove all profiles config from application.yml, it works fine:

file: file1.txt

因此,这意味着上下文扫描不是读取配置文件变量。

So, it means that context scan is not reading the profile variable.

此外,如果我以编程方式设置活动配置文件,它也不会解析属性:

Also, if I set active profile "programatically", it doesn't resolve the properties either:

context.getEnvironment().setActiveProfiles("p1");


推荐答案

最简单的方法是让springboot处理所有问题只需使用 @Value ,或者使用以下注释

The simplest approach is to let springboot handle it all and just use @Value, or alternatively make use of the following annotations

@Configuration
@EnableConfigurationProperties
@ConfigurationProperties("property.prefix.if.any")

如果您需要使用 @PropertySource 方法,这就是正在发生的事情......

If you need to use the @PropertySource approach, here's what's happening...

<你引用的code> YamlPropertyLoaderFactory 有以下代码:

public class YamlPropertyLoaderFactory extends DefaultPropertySourceFactory {
    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
        if (resource == null){
            return super.createPropertySource(name, resource);
        }

        return new YamlPropertySourceLoader().load(resource.getResource().getFilename(), resource.getResource(), null);
    }
}

的第三个参数YamlPropertySourceLoader.load()方法实际上是您想要属性的配置文件名称。由于此示例传入null,因此只返回yml文件中的属性集,而不是特定的配置文件。

The third parameter to the YamlPropertySourceLoader.load() method is actually the profile name that you want the properties for. As this example passes in null it just returns the set of properties from the yml file not for a specific profile.

即。

spring:
  profiles:
    active: p1

---

我认为在 YamlPropertyLoaderFactory ,虽然您可以尝试类似...

I don't think it's easy to pick up the active profile name in the YamlPropertyLoaderFactory, although you could try something like...

public class YamlPropertyLoaderFactory extends DefaultPropertySourceFactory {
    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
        if (resource == null){
            return super.createPropertySource(name, resource);
        }

        String activeProfile = System.getProperty("spring.profiles.active");
        return new YamlPropertySourceLoader().load(resource.getResource().getFilename(), resource.getResource(), activeProfile);
    }
}

或者你在yml中有活动的个人资料名称文件,您可以使用null调用 YamlPropertySourceLoader()。load 来获取spring.profiles.active属性,然后再次调用它以加载所需的yml文件的实际部分。

Or as you have the active profile name in the yml file, you could call YamlPropertySourceLoader().load with null to get the spring.profiles.active property then call it again to load the actual part of the yml file you want.

public class YamlPropertyLoaderFactory extends DefaultPropertySourceFactory {
    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
        if (resource == null){
            return super.createPropertySource(name, resource);
        }
        PropertySource<?> source = new YamlPropertySourceLoader().load(resource.getResource().getFilename(), resource.getResource(), null);
        String activeProfile = source.getProperty("spring.profiles.active");
        return new YamlPropertySourceLoader().load(resource.getResource().getFilename(), resource.getResource(), activeProfile);
    }
}

YamlPropertySourceLoader 在2018年2月更改了( YitlPropertySourceLoader责备Git回购视图)。它现在返回一个propertySource列表,并且在load方法上没有第三个参数。

YamlPropertySourceLoader was changed back in feb 2018 (YamlPropertySourceLoader blame view in Git repo). It now returns a list of propertySource and does not have the third parameter on the load method.

如果您在yml文件中有spring.profiles.active属性,则可以使用较新版本的 YamlPropertySourceLoader执行以下操作

Provided you have the spring.profiles.active property in the yml file you'd be able to do the following with the newer version of YamlPropertySourceLoader

public class YamlPropertyLoaderFactory extends DefaultPropertySourceFactory {

    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
        if (resource == null){
            return super.createPropertySource(name, resource);
        }
        List<PropertySource<?>> sources = new YamlPropertySourceLoader().load(resource.getResource().getFilename(), resource.getResource());
        for (PropertySource<?> checkSource : sources) {
            if (checkSource.containsProperty("spring.profiles.active")) {
                String activeProfile = (String) checkSource.getProperty("spring.profiles.active");
                for (PropertySource<?> source : sources) {
                    if (activeProfile.trim().equals(source.getProperty("spring.profiles"))) {
                        return source; 
                    }
                }
            }
        }
        return sources.get(0);
    }

}

这篇关于从application.yml读取属性时,将忽略Spring配置文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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