我想從application.properties
遷移到application.yaml
,并使用配置文件和每個配置文件不同的@Configuration
-classes。
預(yù)期行為:TestEnvPrinter.printEnv: env = test
實(shí)際行為:DefaultEnvPrinter.printEnv(): env = default, profile = test
為什么Spring只使用DefaultAppConfig
而忽略TestAppConfig
@Configuration
-class?
一些應(yīng)用程序文件:
application.yaml
:
spring:
profiles:
active: test
app:
env: default
application-test.yaml
:
app:
env: test
DefaultAppConfig.java
:
@ComponentScan("ru.albert_rayanov")
@Configuration
@PropertySource("classpath:application.yaml")
public class DefaultAppConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer properties() {
PropertySourcesPlaceholderConfigurer result = new PropertySourcesPlaceholderConfigurer();
YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean();
yamlFactory.setResources(new ClassPathResource("application.yaml"));
result.setProperties(Objects.requireNonNull(yamlFactory.getObject()));
return result;
}
}
TestAppConfig.java
:
@Configuration
@Profile("test")
@PropertySources(value = {@PropertySource("classpath:application-test.yaml")})
public class TestAppConfig {
@Bean
public EnvPrinter envPrinter() {
return new TestEnvPrinter();
}
}
DefaultEnvPrinter.java
:
@Component
@Primary
public class DefaultEnvPrinter implements EnvPrinter {
@Value("${app.env}")
private String env;
@Value("${spring.profiles.active}")
private String profile;
@Override
public void printEnv() {
System.out.println("DefaultEnvPrinter.printEnv(): env = " + env + ", profile = " + profile);
}
}
TestEnvPrinter.java
:
@Component
public class TestEnvPrinter implements EnvPrinter {
@Value("${app.env}")
private String env;
@Override
public void printEnv() {
System.out.println("TestEnvPrinter.printEnv: env = " + env);
}
}
ProfileWorker.java
:
@Component
public class ProfileWorker {
private final EnvPrinter envPrinter;
public ProfileWorker(EnvPrinter envPrinter) {
this.envPrinter = envPrinter;
}
public void doWork() {
envPrinter.printEnv();
}
}
Main.java
:
public class Main {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(DefaultAppConfig.class);
context.getBean(ProfileWorker.class).doWork();
}
}
pom.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>ru.albert_rayanov</groupId>
<artifactId>spring_1_7_profiles</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.0.8</version>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.33</version>
</dependency>
</dependencies>
</project>
Spring Framework's
@PropertySource
沒有out-of-the-box對YAML的支持。它會將您的YAML文件視為.properties
文件,因此無法找到預(yù)期的配置。您可以編寫一個自定義的PropertySourceFactory
實(shí)現(xiàn)來添加YAML支持,并使用@PropertySource
的factory
屬性指定工廠。正如Baeldung的這篇文章中所描述的,
PropertySourceFactory
實(shí)現(xiàn)相當(dāng)簡單: