【问题标题】:Property placeholders with YamlPropertiesFactoryBean and Spring Boot使用 YamlPropertiesFactoryBean 和 Spring Boot 的属性占位符
【发布时间】:2018-12-07 13:17:55
【问题描述】:

我正在将一个小型“旧版”应用程序迁移到 Spring Boot,并遇到了与 YamlPropertiesFactoryBean 结合使用的属性占位符问题。该应用程序使用 Spring XML 配置。

我在项目中添加了一个 Spring Boot “main”,如下所示:

@SpringBootApplication
@ImportResource("classpath:spring-config.xml")
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

我已将application.yaml 放入/config。它正在被 Spring boot 拾取,我可以通过导入的 spring-config.xml 中的 bean 声明中的属性替换 (${some.prop}) 访问其中定义的属性。例如

<bean id="myRouteBuilder" class="org.camelSpringBoot.test.MyRouteBuilder">
    <property name="someProp" value="${prop.from.application.yaml}"/>
</bean>

除了当使用 org.springframework.beans.factory.config.YamlPropertiesFactoryBean 读取额外的外部配置文件时:org.springframework.core.io.FileSystemResource 的构造函数 arg 中的文件位置属性无法解析:

<bean id="yamlProperties" class="org.springframework.beans.factory.config.YamlPropertiesFactoryBean">
    <property name="resources">
        <list>
            <bean class="org.springframework.core.io.FileSystemResource">
                <constructor-arg value="${service.config.loc}" />
            </bean>
        </list>
    </property>
</bean>

产量

java.io.FileNotFoundException: ${service.config.loc}

如果我硬编码外部配置的位置,则外部 YAML 文件中使用的属性也不会解析。

application.yaml:

security:
  keystore:
    loc:      /security/my.keystore

外部配置:

services:
  a:
    ssl:
      secret: ${security.keystore.loc}

java.lang.RuntimeException:无法打开密钥库/信任库 ${security.keystore.loc}

请注意,该错误抱怨逐字属性。

YamlPropertiesFactoryBean 实例在 spring-config.xml 中声明,就像其他成功使用属性占位符的 bean 一样(意味着属性被它们的值替换)。为什么YamlPropertiesFactoryBean会失败

是否可以为外部 YAML 文档启用占位符解析?

【问题讨论】:

  • 仅仅添加一个将文件读入属性的bean是行不通的。在加载和解析属性旁边不是基于多路传递的解决方案。因此,尝试添加属性对象并期望解决这些问题是行不通的。此外,您的 YAML 中的属性与您使用的占位符不同。
  • @M.Deinum,嗯,Spring(Boot)中的很多东西都可以正常工作。 ;-) 无论如何,从 YAML 文件中读取的属性也会以 Environment 作为属性源。所以我想知道是否可以通过一些巧妙的配置来触发属性替换。 (我没有看到属性名称不匹配在哪里?您能更精确或直接编辑问题吗?无论如何,这些不是真正的值。实际配置包含应用程序特定的名称。)

标签: spring spring-boot


【解决方案1】:

我不知道它是否在你想要做的工作。属性解析发生在 BeanDefinition 完成后,因此只能使用 Spring Bean,而不是像 yaml 文件这样的任意文件。

大多数构建工具(gradle、maven)都包含在构建时解析这些占位符的功能。这可能是您的解决方案吗?

【讨论】:

  • 不确定我是否理解您关于属性解析与 bean 创建顺序的评论。关于使用 Maven:我想使用属性解析的原因是因为我需要能够从 Java 系统属性或操作系统环境变量中获取值,并且只在实际 YAML 配置文件中提供默认值作为后备。因此,构建时属性解析无法解决问题。
  • 您只能对 Bean 定义使用属性解析。因此,您使用该文件的方法不起作用。您需要将此动态属性移动到 Spring bean 定义中才能工作,或者提出完全不同的方法。这种动态价值的来源是什么?
  • 借助 Spring Boot,我可以在 /config/application.yaml 中使用属性解析。 (see "Placeholders in Properties")。所以属性解析不仅限于 Bean 定义,是吗?
  • 是的,但这仅适用于系统/环境变量。这是一个典型的chicken/egg problem。 spring应该如何知道实际来源是什么?
猜你喜欢
  • 2014-07-16
  • 2016-02-22
  • 2011-09-22
  • 2019-04-15
  • 2011-12-10
  • 1970-01-01
  • 2017-09-15
  • 2021-03-08
  • 1970-01-01
相关资源
最近更新 更多