application.properties中的Key-value对可以算作环境变量吗?

Can Key value pairs in application.properties be considered as environmental variables?

新 spring 启动。

在探索 spring 引导环境变量时,了解到, 环境变量可以通过 ${KeyName} 从代码中访问。

有一个问题,例如

案例一: 在 @Configuration 文件中,我们使用 @Value(value = "${KeyName}") 访问 application.properties 中的键。 因此,我们使用几乎相同的语法来访问环境变量和访问 application.properties.

中的键

案例二: 当尝试使用 system.getEnv("keyname") 访问 application.properties 中的键时,我只得到 null.

案例三: 最近使用 spring boot.

在 kubernetes 中使用 configmap

配置文件看起来像,

spec:
  containers:
  - name: demo-configconsumercontainer
    image: springbootappimage:latest
    ports:
    - containerPort: 8080
    envFrom:
      - configMapRef:
          name: example-configmap

configMap 中的所有值都作为环境变量导出,并且 我通过 @Value(value = "${KeyName}")system.getEnv(KeyName).

访问这些值
  1. 我的问题是,当情况 2 不工作时,情况 3 如何工作。
  2. Spring 启动是否允许 ${KeyName} 而不是 system.getEnv(KeyName) 访问? (即案例 2)

有人可以在这里澄清我的问题吗?

使用@Value 注释,您可以从许多 属性 源 中访问 属性,例如在 application.properties 或环境变量中,并且更多 属性 个来源。

这里的要点是这些属性来源的排序

以下是在各种来源中查找 属性 的顺序。

  1. 主目录上的 Devtools 全局设置属性(~/.spring-boot-devtools.properties,当 devtools 处于活动状态时)。
  2. @TestPropertySource 对您的测试进行注释。
  3. @SpringBootTest#properties 注释属性在你的测试中。
  4. 命令行参数。
  5. 来自 SPRING_APPLICATION_JSON 的属性(内联 JSON 嵌入环境变量或系统 属性)
  6. ServletConfig 初始化参数。
  7. ServletContext 初始化参数。
  8. 来自 java 的 JNDI 属性:comp/env.
  9. Java 系统属性 (System.getProperties())。
  10. OS 环境变量。
  11. 只具有随机属性的 RandomValuePropertySource。*。
  12. Profile-specific 打包 jar 之外的应用程序属性(application-{profile}.properties 和 YAML 变体)
  13. Profile-specific 打包在您的 jar 中的应用程序属性(application-{profile}.properties 和 YAML 变体)
  14. 打包的 jar(application.properties 和 YAML 变体)之外的应用程序属性。
  15. 打包在您的 jar 中的应用程序属性(application.properties 和 YAML 变体)。
  16. @Configuration 上的@PropertySource 注释类。
  17. 默认属性(使用 SpringApplication.setDefaultProperties 指定)。

在您的例子中,属性 要么在环境变量中声明,要么在 application.yaml 中声明,因此可以使用 @Value 注释访问。

查看 Spring 文档:

https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html

Spring 包括环境变量作为潜在的 属性 来源,但不会将其以其他方式定义的属性导出为环境变量。所以它不是一条双向街道,这就是案例 #2 不起作用的原因。

案例 #3 是一个独立的现实,当 K8s 运行以这种方式使用环境变量定义的容器时,它使这些变量在容器环境中可用。任何能够读取环境变量的软件系统或编程语言都能够引用这些变量,包括 Java 代码。这与 Java 或 Spring 无关...它只是将环境变量注入运行时环境的另一种方法。

更新:在我发布自己的答案之前,我没有看到@ShaileshPratapwar 的答案。看起来我们的答案大致相同,尽管我认为您最好知道 属性 来源列表及其优先顺序的来源。 Spring 文档对它进行了非常明确的定义。