从application.yml读取属性时,将忽略Spring配置文件 [英] Spring profile is ignored when reading properties from application.yml
问题描述
我有扫描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屋!