Spring "spring.profiles.include" 覆盖
Spring "spring.profiles.include" overrides
我的意图是在 spring 引导应用程序中有两个配置文件 - 开发和生产一个。开发配置文件只是为了覆盖生产配置文件的一些变量(例如内存数据库而不是云中的数据库)。由于我预计将来会对生产配置文件进行一些更改,因此在开发配置文件中复制变量似乎不是解决方案。
所以,在 Spring Reference 中,我读到 spring.profiles.include
应该只从引用的配置文件中添加属性。
Sometimes, it is useful to have profile-specific properties that add to the active profiles rather than replace them. The spring.profiles.include
property can be used to unconditionally add active profiles.
但是,根据我的检查,它会覆盖它。因此,当在单独的 yaml 文件中有两个配置文件 foo 和 bar 时:
申请-foo.yaml:
myproperty: 44
申请-bar.yaml:
spring:
profiles:
include: foo
active: bar,foo
myproperty: 55
并且在IDE中设置-Dspring.profiles.active=bar
变量,myproperty
的运行时值为44。这意味着bar
被foo
覆盖了应该只添加属性,而不是覆盖它们。启动应用程序时,我得到:
The following profiles are active: foo,bar
我在另一个问题中按照此 answer 的建议将 spring.profiles.active=bar
添加到 application-bar.yaml
,但它没有效果 - 当 属性 存在时没有区别或不(我也尝试使用破折号列表而不是逗号分隔值)。
我的问题是,它应该如何工作(然后 Spring 参考具有误导性)?如果是这样,有什么解决办法吗?
将 link 添加到 github 上的应用程序源代码。
根据 spring 引导文档 here,spring.profiles.include
用于添加来自其他配置文件的属性。如果 属性 不在活动配置文件中,它将从其他配置文件添加 属性。但是如果它存在,那么它将覆盖并且最后一个被应用的获胜
Sometimes, it is useful to have profile-specific properties that add to the active profiles rather than replace them. The spring.profiles.include
property can be used to unconditionally add active profiles.
我们实施 Spring 活动配置文件的方式略有不同。假设默认属性文件 application.yml
包含在生产和开发环境中相同的所有默认值。
为分别名为 application-prd.yml
和 application-dev.yml
的生产和开发文件创建单独的属性。这些文件可能包含额外的属性或覆盖一些默认属性。
在应用程序启动期间,我们将 spring.profiles.active
作为环境变量传递。例如,
-Dspring.profiles.active=prd
将接手 application-prd.yml
以及 application.yml
或
-Dspring.profiles.active=dev
将接手 application-dev.yml
以及 application.yml
您可以在 application-bar.yaml
中添加新的配置文件:
spring.profiles.include: foo,foo-override
myproperty: 33
---
spring.profiles: foo-override
myproperty: 55
顺序是:33 in bar
被 44 in foo
覆盖 被 55 in foo-override
覆盖。
给定:
- 文件:
application-default.yml, application-foo.yml, application-bar.yml
myproperty: default
在 application-default.yml
myproperty: foo
在 application-foo.yml
myproperty: bar
在 application-bar.yml
我认为这 2 个使用配置文件的用例在含义上有点相反:
在最常见的情况下(-Dspring.profiles.active
但没有 spring.profiles.include
):
- 当配置文件 foo 或 boo 被激活时,属性来自
application-foo.yml(或 application-bar.yml)将 add/override
来自 application-default.yml.
- 当配置文件 foo,bar 被激活时,bar 中的属性将 add/override 来自 application-foo.yml 的属性,然后是来自 application-default.yml.
的属性
例如:-Dspring.profiles.active=foo,bar
来自 application-bar.yml 的 属性 获胜(覆盖)-> myproperty: bar
第二种情况(使用spring.profiles.include
)
- 来自 include 语句的属性 add/overrides 来自使用
spring.profiles.include
的 application-*.yml 文件的属性
即:如果 application-boo.yml
包含 spring.profiles.include=foo
,则 application-foo.bar adds/override properties from from application-bar.yml
的属性 add/override 来自 application-default.yml.
的属性
另一方面(我想)如果 application-boo.yml 包含 spring.profiles.include=default,foo
那么 application-foo.yml
中的属性将 add/override 来自 application-default.yml
的属性add/override 来自 application-bar.yml
的那些。所以myproperty: bar
。我不建议将 default
与 spring.profiles.include
结合使用,因为这样它会混合两种情况,并且考虑到 application-default.yml
在 springboot 中有特殊处理,覆盖策略是违反直觉的。
我也承认我一点也不喜欢在 application-*.yml 文件中使用 spring.profiles.active
。我更喜欢使用系统属性(包括 Maven)或环境变量来激活配置文件。 IMO 它使整个配置文件对我来说更清晰。
如果根据我(上文)的推理,我走错了路,请告诉我。
Spring Boot 2.4 更改了包含多个配置文件的机制以使用新的 profile groups 功能,而不是在特定于配置文件的文档中使用 spring.profiles.include
。这意味着您的配置不再对 Spring Boot 的新版本有效,需要更改。
也就是说,您的用例似乎不太适合配置文件组,因为它并没有真正结合两个配置文件,而是覆盖了默认值。因此,我建议使用建议 的方法,将公共属性和默认属性放在共享 application.yaml
文件中,并且只在特定配置文件的文档中包含特定于环境的值和覆盖。
application.yaml
spring:
myproperty: 44 # Default value
申请-bar.yaml
spring:
myproperty: 55 # Override default
请注意 Spring 引导支持 multi-document files,因此如果需要,可以将它们组合成一个 application.yaml
文件:
spring:
myproperty: 44 # Default value
---
spring.config.activate.on-profile: bar # These configs apply to the bar profile
spring:
myproperty: 55 # Override default
相关 2.4 更改
自 Spring Boot 2.4 起,不再可能在特定于配置文件的文档中使用 spring.profiles.include
,除非 legacy mode is enabled using spring.config.use-legacy-processing=true
. Per the 2.4 Spring Boot Config Data Migration Guide:
you can still use the spring.profiles.include property, but only in non profile-specific documents.
此方法已被 profile groups 功能取代。根据 迁移指南:
As discussed above, it’s no longer possible to use spring.profiles.include
in a profile-specific document so this file isn’t valid.
Since this use-case is quite common, we’ve tried to provide another way to support it. In Spring Boot 2.4 you can use the “profile groups” feature.
此功能记录在 Spring 引导参考指南的 Profile Groups 部分:
A profile group allows you to define a logical name for a related group of profiles.
For example, we can create a production
group that consists of our proddb
and prodmq
profiles.
spring:
profiles:
group:
production:
- "proddb"
- "prodmq"
Our application can now be started using --spring.profiles.active=production
to active the production
, proddb
and prodmq
profiles in one hit.
迁移指南points out spring.profile.group
属性 不能在特定配置文件中使用。
The spring.profile.group
property cannot be used in profile-specific documents.
我的意图是在 spring 引导应用程序中有两个配置文件 - 开发和生产一个。开发配置文件只是为了覆盖生产配置文件的一些变量(例如内存数据库而不是云中的数据库)。由于我预计将来会对生产配置文件进行一些更改,因此在开发配置文件中复制变量似乎不是解决方案。
所以,在 Spring Reference 中,我读到 spring.profiles.include
应该只从引用的配置文件中添加属性。
Sometimes, it is useful to have profile-specific properties that add to the active profiles rather than replace them. The
spring.profiles.include
property can be used to unconditionally add active profiles.
但是,根据我的检查,它会覆盖它。因此,当在单独的 yaml 文件中有两个配置文件 foo 和 bar 时:
申请-foo.yaml:
myproperty: 44
申请-bar.yaml:
spring:
profiles:
include: foo
active: bar,foo
myproperty: 55
并且在IDE中设置-Dspring.profiles.active=bar
变量,myproperty
的运行时值为44。这意味着bar
被foo
覆盖了应该只添加属性,而不是覆盖它们。启动应用程序时,我得到:
The following profiles are active: foo,bar
我在另一个问题中按照此 answer 的建议将 spring.profiles.active=bar
添加到 application-bar.yaml
,但它没有效果 - 当 属性 存在时没有区别或不(我也尝试使用破折号列表而不是逗号分隔值)。
我的问题是,它应该如何工作(然后 Spring 参考具有误导性)?如果是这样,有什么解决办法吗?
将 link 添加到 github 上的应用程序源代码。
根据 spring 引导文档 here,spring.profiles.include
用于添加来自其他配置文件的属性。如果 属性 不在活动配置文件中,它将从其他配置文件添加 属性。但是如果它存在,那么它将覆盖并且最后一个被应用的获胜
Sometimes, it is useful to have profile-specific properties that add to the active profiles rather than replace them. The
spring.profiles.include
property can be used to unconditionally add active profiles.
我们实施 Spring 活动配置文件的方式略有不同。假设默认属性文件 application.yml
包含在生产和开发环境中相同的所有默认值。
为分别名为 application-prd.yml
和 application-dev.yml
的生产和开发文件创建单独的属性。这些文件可能包含额外的属性或覆盖一些默认属性。
在应用程序启动期间,我们将 spring.profiles.active
作为环境变量传递。例如,
-Dspring.profiles.active=prd
将接手 application-prd.yml
以及 application.yml
或
-Dspring.profiles.active=dev
将接手 application-dev.yml
以及 application.yml
您可以在 application-bar.yaml
中添加新的配置文件:
spring.profiles.include: foo,foo-override
myproperty: 33
---
spring.profiles: foo-override
myproperty: 55
顺序是:33 in bar
被 44 in foo
覆盖 被 55 in foo-override
覆盖。
给定:
- 文件:
application-default.yml, application-foo.yml, application-bar.yml
myproperty: default
在 application-default.ymlmyproperty: foo
在 application-foo.ymlmyproperty: bar
在 application-bar.yml
我认为这 2 个使用配置文件的用例在含义上有点相反:
在最常见的情况下(
-Dspring.profiles.active
但没有spring.profiles.include
):- 当配置文件 foo 或 boo 被激活时,属性来自 application-foo.yml(或 application-bar.yml)将 add/override 来自 application-default.yml.
- 当配置文件 foo,bar 被激活时,bar 中的属性将 add/override 来自 application-foo.yml 的属性,然后是来自 application-default.yml. 的属性
例如:
-Dspring.profiles.active=foo,bar
来自 application-bar.yml 的 属性 获胜(覆盖)->myproperty: bar
第二种情况(使用
spring.profiles.include
)- 来自 include 语句的属性 add/overrides 来自使用
spring.profiles.include
的 application-*.yml 文件的属性
即:如果
的属性application-boo.yml
包含spring.profiles.include=foo
,则application-foo.bar adds/override properties from from application-bar.yml
的属性 add/override 来自 application-default.yml.另一方面(我想)如果 application-boo.yml 包含
spring.profiles.include=default,foo
那么application-foo.yml
中的属性将 add/override 来自application-default.yml
的属性add/override 来自application-bar.yml
的那些。所以myproperty: bar
。我不建议将default
与spring.profiles.include
结合使用,因为这样它会混合两种情况,并且考虑到application-default.yml
在 springboot 中有特殊处理,覆盖策略是违反直觉的。- 来自 include 语句的属性 add/overrides 来自使用
我也承认我一点也不喜欢在 application-*.yml 文件中使用 spring.profiles.active
。我更喜欢使用系统属性(包括 Maven)或环境变量来激活配置文件。 IMO 它使整个配置文件对我来说更清晰。
如果根据我(上文)的推理,我走错了路,请告诉我。
Spring Boot 2.4 更改了包含多个配置文件的机制以使用新的 profile groups 功能,而不是在特定于配置文件的文档中使用 spring.profiles.include
。这意味着您的配置不再对 Spring Boot 的新版本有效,需要更改。
也就是说,您的用例似乎不太适合配置文件组,因为它并没有真正结合两个配置文件,而是覆盖了默认值。因此,我建议使用建议 application.yaml
文件中,并且只在特定配置文件的文档中包含特定于环境的值和覆盖。
application.yaml
spring:
myproperty: 44 # Default value
申请-bar.yaml
spring:
myproperty: 55 # Override default
请注意 Spring 引导支持 multi-document files,因此如果需要,可以将它们组合成一个 application.yaml
文件:
spring:
myproperty: 44 # Default value
---
spring.config.activate.on-profile: bar # These configs apply to the bar profile
spring:
myproperty: 55 # Override default
相关 2.4 更改
自 Spring Boot 2.4 起,不再可能在特定于配置文件的文档中使用 spring.profiles.include
,除非 legacy mode is enabled using spring.config.use-legacy-processing=true
. Per the 2.4 Spring Boot Config Data Migration Guide:
you can still use the spring.profiles.include property, but only in non profile-specific documents.
此方法已被 profile groups 功能取代。根据 迁移指南:
As discussed above, it’s no longer possible to use
spring.profiles.include
in a profile-specific document so this file isn’t valid.Since this use-case is quite common, we’ve tried to provide another way to support it. In Spring Boot 2.4 you can use the “profile groups” feature.
此功能记录在 Spring 引导参考指南的 Profile Groups 部分:
A profile group allows you to define a logical name for a related group of profiles.
For example, we can create a
production
group that consists of ourproddb
andprodmq
profiles.spring: profiles: group: production: - "proddb" - "prodmq"
Our application can now be started using
--spring.profiles.active=production
to active theproduction
,proddb
andprodmq
profiles in one hit.
迁移指南points out spring.profile.group
属性 不能在特定配置文件中使用。
The
spring.profile.group
property cannot be used in profile-specific documents.