问题
My intention is to have two profiles in a spring boot application - development and production one. Development profile is meant just to override some variables of production profile (like in-memory database instead of database in the cloud). As I expect some changes to be done to production profile in the future, duplicating variables in development profile doesn't seem to be a solution.
So, in Spring Reference I read that spring.profiles.include
is supposed to only add properties from referenced profile, but from what I've checked it rather overrides it. So, when having two profiles foo and bar, in separate yaml files:
application-foo.yaml:
myproperty: 44
application-bar.yaml:
spring:
profiles:
include: foo
active: bar,foo
myproperty: 55
And setting -Dspring.profiles.active=bar
variable in IDE, the runtime value of myproperty
is 44. That means that bar
, is overriden with foo
which was supposed to only add properties, but not to override them. When starting the application, I get:
The following profiles are active: foo,bar
I added spring.profiles.active=bar
to application-bar.yaml
as suggested by this answer, in another question, but it has no effect - there is no difference when property is there or not (I also tried using dash listing instead of comma separated values).
My question is, is it how it is supposed to work (then Spring Reference is misleading)? If so, are there any solutions for that?
Adding a link to the application source code on a github.
回答1:
We implemented the Spring active profiles in a slightly different way. Let's say the default properties file, application.yml
, contains all default values which is same in both production and development environments.
Create separate properties for production and development files named application-prd.yml
and application-dev.yml
respectively. These files may contain extra properties or override some of the default properties.
During application startup, we pass the spring.profiles.active
as an environment variable. For example,
-Dspring.profiles.active=prd
will pick up application-prd.yml
along with application.yml
or
-Dspring.profiles.active=dev
will pick up application-dev.yml
along with application.yml
回答2:
According to the spring boot documentation here, spring.profiles.include
is used to add the properties from other profiles. It will add the property from other profiles if the property is not present in active one. But if it is present, then it will overwrite and the last one to be applied wins
回答3:
You could add a new profile in the application-bar.yaml
:
spring.profiles.include: foo,foo-override
myproperty: 33
---
spring.profiles: foo-override
myproperty: 55
The order is: 33 in bar
overridden by 44 in foo
overridden by 55 in foo-override
.
回答4:
There are two parts to the problems here:
First is present in the answer refered in original question (here). I.e. how to inherit properties from profile. The answer is to include original profile. However for the situation we have it might be not needed.
Second problem is activating profiles done differently. I believe (but might turn out wrong) that in referred question the OP does not activate profile with this:
-Dspring.profiles.active=bar
This line overrides whatever is provided in the profile. So for this case the simplest solution to inherit properties would be to change the line in IDE to:
-Dspring.profiles.active=bar,foo
you can then omit properties in foo the are present in bar and also omit spring.profiles.include, however in that case foo will not be standalone profile. If that's ok - it will work this way.
回答5:
Given:
- The files:
application-default.yml, application-foo.yml, application-bar.yml
myproperty: default
in application-default.ymlmyproperty: foo
in application-foo.ymlmyproperty: bar
in application-bar.yml
I think these 2 use cases of using profiles are a little bit opposite in the meaning:
In the most common case (
-Dspring.profiles.active
but nospring.profiles.include
):- When profile foo or boo are activated the properties from application-foo.yml (or application-bar.yml) will add/override the ones from application-default.yml.
- When profiles foo,bar are activated then properties from bar will add/override those from application-foo.yml and then those from application-default.yml.
E.g:
-Dspring.profiles.active=foo,bar
the property from application-bar.yml wins (overrides) ->myproperty: bar
In the second case (
spring.profiles.include
is used)- The properties from the include statement add/overrides the properties from the application-*.yml files which uses
spring.profiles.include
I.e.: If
application-boo.yml
contains thespring.profiles.include=foo
then properties fromapplication-foo.bar adds/override properties from from application-bar.yml
which add/override those from application-default.yml.On the other hand (I suppose) if application-boo.yml includes the
spring.profiles.include=default,foo
then properties fromapplication-foo.yml
will add/override those fromapplication-default.yml
which add/overrides those fromapplication-bar.yml
. Somyproperty: bar
. I wouldn't recommend the usage ofdefault
in combination withspring.profiles.include
because this way it mixes the two cases and the override strategy is counterintuitive consideringapplication-default.yml
has a special treatment in springboot.- The properties from the include statement add/overrides the properties from the application-*.yml files which uses
I also admit I am not at all a fan of the spring.profiles.active
usage in application-*.yml files. I prefer to activate the profiles with system properties (maven included) or env variables. IMO it makes the whole profiles thing clearer to me.
If with my (herein above)reasoning I am on the wrong path please let me know.
来源:https://stackoverflow.com/questions/47368086/spring-spring-profiles-include-overrides