Spring(不开机)从多个项目加载多个yml文件
Spring (not boot) load multiple yml files from multiple projects
所以我阅读了关于如何配置 Spring 引导以识别比 application.yml
更多的 yml 文件以及如何包含这些文件的 dosens af 文章——甚至来自子项目。然而,很难找到描述 "pure" Spring 的文章。但是我认为我正朝着正确的方向前进,我只是无法取回我的配置值。
这是一个直接的多项目 gradle 构建 - 为简单起见 - 两个项目。一个项目是 "main" spring 项目 - 即。 Spring 上下文已在此项目中初始化。另一个是带有一些数据库实体和数据源配置的 "support" 模块。我们使用基于注释的配置。
我希望能够在支持模块中定义一组配置属性,并根据任何 spring 配置文件处于活动状态,相应地加载数据源配置。
SA post 跟随不同答案中的不同链接让我走了很远,并由此构成了我的解决方案。结构及代码如下:
mainproject
src
main
groovy
Application.groovy
resourcers
application.yml
submodule
src
main
groovy
PropertiesConfiguration.groovy
DataSource.groovy
resources
datasource.yml
PropertiesConfiguration.groovy
使用 PropertySourcesPlaceholderConfigurer
添加 datasource.yml
:
@Configuration
class PropertiesConfiguration {
@Bean
public PropertySourcesPlaceholderConfigurer configure() {
PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer()
YamlPropertiesFactoryBean yamlPropertiesFactoryBean = new YamlPropertiesFactoryBean()
yamlPropertiesFactoryBean.setResources(new ClassPathResource("datasource.yml"))
configurer.setProperties(yamlPropertiesFactoryBean.getObject())
return configurer
}
}
然后 Datasource.groovy
应该读取基于 spring 配置文件的值,使用(为便于阅读而减少代码):
@Autowired
Environment env
datasource.username = env.getProperty("datasource.username")
env.getProperty
return 为空。无论什么 spring 配置文件处于活动状态。我可以使用 @Value 批注访问配置值,但是活动配置文件不受尊重,它 return 一个值,即使它没有为该配置文件定义。我的 yml 看起来像这样:
---
spring:
profiles: development
datasource:
username: sa
password:
databaseUrl: jdbc:h2:mem:tests
databaseDriver: org.h2.Driver
我可以从 Application.groovy 使用调试器检查我的 ApplicationContext 并确认我的 PropertySourcesPlaceholderConfigurer
存在并且值已加载。检查 applicationContext.environment.propertySources
它不存在。
我错过了什么?
使用 PropertySourcesPlaceholderConfigurer
不会向 Environment
添加属性。在配置 class 的 class 级别上使用类似 @PropertySource("classpath:something.properties")
的内容将向 Environment
添加属性,但遗憾的是,这不适用于 yaml
文件。
因此,您必须手动将从 yaml
文件读取的属性添加到您的 Environment
。这是一种方法:
@Bean
public PropertySourcesPlaceholderConfigurer config(final ConfigurableEnvironment confenv) {
final PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
final YamlPropertiesFactoryBean yamlProperties = new YamlPropertiesFactoryBean();
yamlProperties.setResources(new ClassPathResource("datasource.yml"));
configurer.setProperties(yamlProperties.getObject());
confenv.getPropertySources().addFirst(new PropertiesPropertySource("datasource", yamlProperties.getObject()));
return configurer;
}
使用此代码,您可以以这两种方式之一注入属性:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = PropertiesConfiguration.class)
public class ConfigTest {
@Autowired
private Environment environment;
@Value("${datasource.username}")
private String username;
@Test
public void props() {
System.out.println(environment.getProperty("datasource.username"));
System.out.println(username);
}
}
根据问题中提供的属性,这将打印 "sa" 两次。
编辑:现在似乎并不真正需要 PropertySourcesPlaceholderConfigurer
,因此代码可以简化为以下内容,但仍会产生相同的输出。
@Autowired
public void config(final ConfigurableEnvironment confenv) {
final YamlPropertiesFactoryBean yamlProperties = new YamlPropertiesFactoryBean();
yamlProperties.setResources(new ClassPathResource("datasource.yml"));
confenv.getPropertySources().addFirst(new PropertiesPropertySource("datasource", yamlProperties.getObject()));
}
编辑 2:
我现在看到您希望将 yaml-file 与一个文件中的多个文档一起使用,并且 Spring boot-style 按配置文件选择。使用常规 Spring 似乎是不可能的。所以我认为你必须将你的 yaml 文件分成几个,命名为 "datasource-{profile}.yml"。然后,这应该可以工作(也许对多个配置文件进行一些更高级的检查等)
@Autowired
public void config(final ConfigurableEnvironment confenv) {
final YamlPropertiesFactoryBean yamlProperties = new YamlPropertiesFactoryBean();
yamlProperties.setResources(new ClassPathResource("datasource-" + confenv.getActiveProfiles()[0] + ".yml"));
confenv.getPropertySources().addFirst(new PropertiesPropertySource("datasource", yamlProperties.getObject()));
}
编辑 3:
也可以使用 Spring 引导中的功能,而无需对您的项目进行完全转换(尽管我还没有在真实项目上实际尝试过)。通过向 org.springframework.boot:spring-boot:1.5.9.RELEASE
添加依赖项,我能够使用单个 datasource.yml
和多个配置文件,如下所示:
@Autowired
public void config (final ConfigurableEnvironment confenv) {
final YamlPropertySourceLoader yamlPropertySourceLoader = new YamlPropertySourceLoader();
try {
final PropertySource<?> datasource =
yamlPropertySourceLoader.load("datasource",
new ClassPathResource("datasource.yml"),
confenv.getActiveProfiles()[0]);
confenv.getPropertySources().addFirst(datasource);
} catch (final IOException e) {
throw new RuntimeException("Failed to load datasource properties", e);
}
}
所以我阅读了关于如何配置 Spring 引导以识别比 application.yml
更多的 yml 文件以及如何包含这些文件的 dosens af 文章——甚至来自子项目。然而,很难找到描述 "pure" Spring 的文章。但是我认为我正朝着正确的方向前进,我只是无法取回我的配置值。
这是一个直接的多项目 gradle 构建 - 为简单起见 - 两个项目。一个项目是 "main" spring 项目 - 即。 Spring 上下文已在此项目中初始化。另一个是带有一些数据库实体和数据源配置的 "support" 模块。我们使用基于注释的配置。
我希望能够在支持模块中定义一组配置属性,并根据任何 spring 配置文件处于活动状态,相应地加载数据源配置。
mainproject
src
main
groovy
Application.groovy
resourcers
application.yml
submodule
src
main
groovy
PropertiesConfiguration.groovy
DataSource.groovy
resources
datasource.yml
PropertiesConfiguration.groovy
使用 PropertySourcesPlaceholderConfigurer
添加 datasource.yml
:
@Configuration
class PropertiesConfiguration {
@Bean
public PropertySourcesPlaceholderConfigurer configure() {
PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer()
YamlPropertiesFactoryBean yamlPropertiesFactoryBean = new YamlPropertiesFactoryBean()
yamlPropertiesFactoryBean.setResources(new ClassPathResource("datasource.yml"))
configurer.setProperties(yamlPropertiesFactoryBean.getObject())
return configurer
}
}
然后 Datasource.groovy
应该读取基于 spring 配置文件的值,使用(为便于阅读而减少代码):
@Autowired
Environment env
datasource.username = env.getProperty("datasource.username")
env.getProperty
return 为空。无论什么 spring 配置文件处于活动状态。我可以使用 @Value 批注访问配置值,但是活动配置文件不受尊重,它 return 一个值,即使它没有为该配置文件定义。我的 yml 看起来像这样:
---
spring:
profiles: development
datasource:
username: sa
password:
databaseUrl: jdbc:h2:mem:tests
databaseDriver: org.h2.Driver
我可以从 Application.groovy 使用调试器检查我的 ApplicationContext 并确认我的 PropertySourcesPlaceholderConfigurer
存在并且值已加载。检查 applicationContext.environment.propertySources
它不存在。
我错过了什么?
使用 PropertySourcesPlaceholderConfigurer
不会向 Environment
添加属性。在配置 class 的 class 级别上使用类似 @PropertySource("classpath:something.properties")
的内容将向 Environment
添加属性,但遗憾的是,这不适用于 yaml
文件。
因此,您必须手动将从 yaml
文件读取的属性添加到您的 Environment
。这是一种方法:
@Bean
public PropertySourcesPlaceholderConfigurer config(final ConfigurableEnvironment confenv) {
final PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
final YamlPropertiesFactoryBean yamlProperties = new YamlPropertiesFactoryBean();
yamlProperties.setResources(new ClassPathResource("datasource.yml"));
configurer.setProperties(yamlProperties.getObject());
confenv.getPropertySources().addFirst(new PropertiesPropertySource("datasource", yamlProperties.getObject()));
return configurer;
}
使用此代码,您可以以这两种方式之一注入属性:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = PropertiesConfiguration.class)
public class ConfigTest {
@Autowired
private Environment environment;
@Value("${datasource.username}")
private String username;
@Test
public void props() {
System.out.println(environment.getProperty("datasource.username"));
System.out.println(username);
}
}
根据问题中提供的属性,这将打印 "sa" 两次。
编辑:现在似乎并不真正需要 PropertySourcesPlaceholderConfigurer
,因此代码可以简化为以下内容,但仍会产生相同的输出。
@Autowired
public void config(final ConfigurableEnvironment confenv) {
final YamlPropertiesFactoryBean yamlProperties = new YamlPropertiesFactoryBean();
yamlProperties.setResources(new ClassPathResource("datasource.yml"));
confenv.getPropertySources().addFirst(new PropertiesPropertySource("datasource", yamlProperties.getObject()));
}
编辑 2:
我现在看到您希望将 yaml-file 与一个文件中的多个文档一起使用,并且 Spring boot-style 按配置文件选择。使用常规 Spring 似乎是不可能的。所以我认为你必须将你的 yaml 文件分成几个,命名为 "datasource-{profile}.yml"。然后,这应该可以工作(也许对多个配置文件进行一些更高级的检查等)
@Autowired
public void config(final ConfigurableEnvironment confenv) {
final YamlPropertiesFactoryBean yamlProperties = new YamlPropertiesFactoryBean();
yamlProperties.setResources(new ClassPathResource("datasource-" + confenv.getActiveProfiles()[0] + ".yml"));
confenv.getPropertySources().addFirst(new PropertiesPropertySource("datasource", yamlProperties.getObject()));
}
编辑 3:
也可以使用 Spring 引导中的功能,而无需对您的项目进行完全转换(尽管我还没有在真实项目上实际尝试过)。通过向 org.springframework.boot:spring-boot:1.5.9.RELEASE
添加依赖项,我能够使用单个 datasource.yml
和多个配置文件,如下所示:
@Autowired
public void config (final ConfigurableEnvironment confenv) {
final YamlPropertySourceLoader yamlPropertySourceLoader = new YamlPropertySourceLoader();
try {
final PropertySource<?> datasource =
yamlPropertySourceLoader.load("datasource",
new ClassPathResource("datasource.yml"),
confenv.getActiveProfiles()[0]);
confenv.getPropertySources().addFirst(datasource);
} catch (final IOException e) {
throw new RuntimeException("Failed to load datasource properties", e);
}
}