1

所以我已经阅读了关于如何配置 Spring boot 以了解更多的 yml 文件application.yml以及如何包含这些文件的文章 - 甚至来自子项目。然而,很难找到描述“纯” Spring 相同的文章。但是我认为我正朝着正确的方向前进,我只是无法恢复我的配置值。

这是一个直接的多项目 gradle 构建 - 为简单起见 - 两个项目。一个项目是“主要”春季项目 - 即。Spring Context 在这个项目中被初始化。另一个是带有一些数据库实体和数据源配置的“支持”模块。我们使用基于注释的配置。

我希望能够在支持模块中定义一组配置属性,并根据激活的弹簧配置文件,相应地加载数据源配置。

这篇SA 帖子让我非常关注不同答案中的不同链接,并由此构成了我的解决方案。结构和代码如下:

mainproject
  src
    main
      groovy
        Application.groovy
    resourcers
      application.yml

submodule
  src
    main
      groovy
        PropertiesConfiguration.groovy
        DataSource.groovy
    resources
      datasource.yml

通过使用PropertiesConfiguration.groovy添加:datasource.ymlPropertySourcesPlaceholderConfigurer

@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应该使用(代码减少可读性)基于弹簧轮廓读取值:

@Autowired
Environment env

datasource.username = env.getProperty("datasource.username")

env.getProperty返回空值。无论何种弹簧轮廓处于活动状态。我可以使用 @Value 注释访问配置值,但是不尊重活动配置文件,即使没有为该配置文件定义它也会返回一个值。我的 yml 看起来(东西)是这样的:

---
spring:
  profiles: development

datasource:
  username: sa
  password:
  databaseUrl: jdbc:h2:mem:tests
  databaseDriver: org.h2.Driver

我可以从 Application.groovy 使用调试器检查我的 ApplicationContext 并确认我的PropertySourcesPlaceholderConfigurer存在并且值已加载。检查applicationContext.environment.propertySources它不存在。

我错过了什么?

4

1 回答 1

2

使用 aPropertySourcesPlaceholderConfigurer不会将属性添加到Environment. 在配置类的类级别上使用类似的东西@PropertySource("classpath:something.properties")会将属性添加到Environment,但遗憾的是这不适用于yaml-files。

因此,您必须手动将从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 文件,并通过配置文件选择 Spring 引导样式。使用常规 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 boot 中的功能(尽管我实际上还没有在真实项目中尝试过)。通过向我添加依赖项, 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);
    }
}
于 2018-03-02T13:02:11.460 回答