In any set of development frameworks, multi-environment management is usually one of the important core features, of course, in the Spring framework is no exception, here we call the Spring Profiles. This feature is simple to say, but it is easy to accidentally mess up the implementation, this article I intend to properly sort out some of the concepts to understand, the management up to not mess up.

Create sample applications
-
Quickly building a project using the Spring Boot CLI
1spring init --dependencies=web --groupId=com.duotify sbprofile1You can also use Spring Initializr to create
Open the project using Visual Studio Code.
1code sbprofile1 -
Add a
HomeControllercontrollerFile path:
src/main/java/com/duotify/sbprofile1/controllers/HomeController.java.1 2 3 4 5 6 7 8 9 10 11 12package com.duotify.sbprofile1.controllers; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HomeController { @GetMapping("/") public String home() { return "Hello World"; } } -
Run the application
1mvn clean spring-boot:runAddendum: You can add a new
<defaultGoal>spring-boot:run</defaultGoal>setting under the<build>node inpom.xml, then you can just typemvnand it will automatically start Spring Boot running in the future! 👍 -
Requesting applications using cURL
Understand the true meaning of Profiles
Since the Spring framework has a bunch of abstract concepts, there are a lot of devilish details that you can’t understand if you don’t take the time to study them. The Spring Profiles mentioned in this article are originally a very simple concept, but there are so many variations when writing Spring Boot that you can get your head in a knot.
Let’s start with the simplest and most abstract concept.
The so-called Profile usually has a name (Profile Name), and this name represents a set of application configurations. You can quickly switch between application configurations with a simple Profile Name, it’s that simple!
The application configuration contains two layers of meaning.
- Configuration is actually a property definition file like
src/main/resources/application.properties. - Components combination means which “components” of the application are enabled, and you can decide what Profile to use to start the application during the running period with simple parameters.
The most common example of using a Profile to manage application configuration is for “multi-environment” deployments, such as when you have an internal “test environment” and a customer-provided “official environment”. The configuration of the two is usually different, but there are some similarities. At this point, we can manage these differences through multiple profiles. After abstraction, we can switch between the different environments as long as we know the Profile Name.
How to use Application Properties
Before you can understand how to manage multiple profiles, you should understand how Application Properties should be used.
The steps of the experiment are as follows.
-
edit the
src/main/resources/application.propertiesproperty file to add amy.profileproperty value1my.profile=dev -
Adjust the
HomeController, add a Private Field, and inject amy.profileattribute value via the@ValueannotationFile path:
src/main/java/com/duotify/sbprofile1/controllers/HomeController.java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17package com.duotify.sbprofile1.controllers; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HomeController { @Value("${my.profile}") private String myProfile; @GetMapping("/") public String home() { return "Hello World: " + this.myProfile; } } -
Testing
1mvn clean spring-boot:runTesting with cURL.
How to pass in attribute values via Maven, command line parameters, environment variables, .env
Sometimes we want to add property values to the application during the “compilation period” via Maven, and then we need a way to pass the properties defined by Maven’s pom.xml into the src/main/resources/application.properties property file.
The steps of the experiment are as follows.
-
edit the
src/main/resources/application.propertiesproperty file.Add a
my.profileproperty value.1my.profile=@my.profile@ -
Adjust the
pom.xmlfile and add a<my.profile>attribute to<properties>1<my.profile>dev2</my.profile> -
Testing
1mvn clean spring-boot:runTesting with cURL
The @my.profile@ syntax in the application.properties properties file is unique in that it declares that you will read the property values from outside, and if Maven has defined properties, by default they will be added as default values when the project is compiled. This syntax also has the advantage of allowing you to Assign Value by various methods only during execution. For example.
-
Importing parameters directly from command line parameters
1mvn clean spring-boot:run -Dmy.profile=dev3 -
Passing in attribute values directly from environment variables
Here is the syntax for setting environment variables in Bash.
1my_profile=dev4 mvn clean spring-boot:runWhen the environment variable encounters an attribute name with a decimal point (
.), remember to convert to underscores (_). -
First package it as a JAR file, and when run by
java -jaryou can also pass in parameters via command line arguments.1mvn clean package1java -Dmy.profile=dev5 -jar target/sbprofile1-0.0.1-SNAPSHOT.jarThis
-Dmy.profile=dev5parameter is passed to the JVM as a system parameter.Remember that
-Dmy.profile=dev5must be set in front of-jar! -
First package it as a JAR file, and when run by
java -jaryou can also pass in parameters via environment variables.1mvn clean package1my_profile=dev6 java -jar target/sbprofile1-0.0.1-SNAPSHOT.jarRemember that
-Dmy.profile=dev5must be set in front of-jar! -
Pass in the parameters directly from the environment variables defined by the
.envfileFirst, add a
.envfile to the project root directory with the following contents.1my_profile=dev7Create a
.vscode/launch.jsonstartup configuration file (VSCode).The focus here is on the
envFilesetting.Press
F5to start the project, and you can read the settings!
How to use Spring Profiles
After understanding how to use and configure Properties files, we can finally get to the main point of this article, which is how to define Spring Profiles profiles.
Here are the steps of the experiment.
-
edit
src/main/resources/application.propertiesproperty fileAdd a
spring.profiles.activeattribute value.1spring.profiles.active=@spring.profiles.active@The
spring.profiles.activeon the left here is the name of the property that the Spring framework will use, while the@spring.profiles.active@on the right is a property that can be passed in from external. -
Adjust Maven’s
pom.xmlconfiguration file and add the<profiles>section settings.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17<profiles> <profile> <id>default</id> <activation> <activeByDefault>true</activeByDefault> </activation> <properties> <spring.profiles.active>default</spring.profiles.active> </properties> </profile> <profile> <id>dev8</id> <properties> <spring.profiles.active>dev8</spring.profiles.active> </properties> </profile> </profiles>What is special about this configuration is that we define
2Profiles, one is ourdefaultprofile and the other is thedev8profile. However, each of the different profiles has a specialspring.profiles.activeattribute defined (you can define multiple attributes), which is used specifically to give Spring applications a reference as to who the currently enabled profiles are.Remember: The properties you define in
pom.xml(<properties>) are not directly referenced by Java programs, they are related as follows.1Java raw file <-- Application properties file (.properties/.yml) <-- External incoming properties (Maven properties / environment variables / command line parameters) -
Modify the
@Valueannotation ofHomeControllerto inject thespring.profiles.activeproperty instead1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17package com.duotify.sbprofile1.controllers; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HomeController { @Value("${spring.profiles.active}") private String myProfile; @GetMapping("/") public String home() { return "Hello World: " + this.myProfile; } } -
Testing
Remember that we now have two profiles,
defaultanddev8. When we start the application withmvn spring-boot:run, we can use-Pplus aProfileNameto enable the profile.1mvn clean spring-boot:run -Pdev8Note: The
Pin-Phere must be capitalized, and the name that follows is the<id>element value inpom.xml!Testing with cURL
If you try to pass in a non-existent
dev9profile name, you will get the default profile.1mvn clean spring-boot:run -Pdev9Note: It is possible to have two Profiles enabled at the same time, separated by a comma with
-P. For example, you can test the enabled Profile name with the following command:mvn help:active-profiles -Pdev,prod
Switching different application property files via Spring Profiles
Another advantage of using the Spring framework’s Profiles feature is that instead of setting the properties in Maven’s pom.xml file, you can set the application properties in different .properties files by using a special naming convention. Please see the comments for the following file name specifications.
|
|
Next we will experiment with the application of multiple profile.
-
Let’s add a
dev9profile to thepom.xmlfile.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23<profiles> <profile> <id>default</id> <activation> <activeByDefault>true</activeByDefault> </activation> <properties> <spring.profiles.active>default</spring.profiles.active> </properties> </profile> <profile> <id>dev8</id> <properties> <spring.profiles.active>dev8</spring.profiles.active> </properties> </profile> <profile> <id>dev9</id> <properties> <spring.profiles.active>dev9</spring.profiles.active> </properties> </profile> </profiles> -
In addition to
application.properties, we create two additional application property filesFile 1:
src/main/resources/application.properties(add amy.nameattribute)File 2:
src/main/resources/application-dev8.properties(add amy.nameattribute)1my.name=JohnFile 3:
src/main/resources/application-dev9.properties(empty content) -
Modify the
@Valueannotation ofHomeControllerto inject thespring.profiles.activeproperty instead1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20package com.duotify.sbprofile1.controllers; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HomeController { @Value("${spring.profiles.active}") private String myProfile; @Value("${my.name}") private String myName; @GetMapping("/") public String home() { return "Hello World: " + this.myName; } } -
Testing
Remember that we now have
3profiles,default,dev8anddev9.First, try not specifying a Profile.
1mvn clean spring-boot:runThen, try to specify Profile
dev8.1mvn clean spring-boot:run -Pdev8Finally, try to specify Profile
dev9.1mvn clean spring-boot:run -Pdev9
Loading different dependent packages via Spring Profiles
The configuration of Spring Profiles not only allows you to set “attributes”, but also allows you to load different <dependencies> dependent packages according to different profiles, such as loading different versions of the same package (testing old and new versions), or the same interface but different packages (different database drivers). This is really great! 👍
-
The following are examples of settings for different versions of the same package.
1 2 3 4 5 6 7 8 9 10 11 12 13<profile> <id>dev8</id> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.7.0</version> </dependency> </dependencies> <properties> <spring.profiles.active>dev8</spring.profiles.active> </properties> </profile>If you want to see the dependent package information after applying a different Profile, you can run the following command.
1mvn dependency:tree -Pdev8 -
The following are examples of settings for same interface with different packages.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35<profiles> <profile> <id>Local</id> <dependencies> <dependency> <groupId>org.hsqldb</groupId> <artifactId>hsqldb</artifactId> <version>2.3.3</version> <classifier>jdk5</classifier> </dependency> </dependencies> <properties> <jdbc.url>jdbc:hsqldb:file:databaseName</jdbc.url> <jdbc.username>a</jdbc.username> <jdbc.password></jdbc.password> <jdbc.driver>org.hsqldb.jdbcDriver</jdbc.driver> </properties> </profile> <profile> <id>MySQL</id> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.38</version> </dependency> </dependencies> <properties> <jdbc.url>jdbc:mysql://mysql.website.ac.uk:3306</jdbc.url> <jdbc.username>user</jdbc.username> <jdbc.password>1234</jdbc.password> <jdbc.driver>com.mysql.jdbc.Driver</jdbc.driver> </properties> </profile> </profiles>
Loading different Beans components via Spring Profiles
Under the Spring framework, all classes annotated with @Component are registered as Beans components, including, of course, classes annotated with @Configuration, since they inherit from the @Component interface.
However, you can simply add the @Profile annotation to the class to declare that Spring is going to load the class under a specific Profile.
Here is an example of how to use it.
-
Create a
UserServiceclass -
Create a
UserServiceDevclass1 2 3 4 5 6 7 8 9 10 11 12 13 14package com.duotify.sbprofile1.services; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; @Component @Profile("dev") public class UserServiceDev { @Bean public UserService getUserService() { return new UserService("Dev"); } }This
UserServiceDevwill only be executed by Spring when thedevprofile is enabled. -
Create a
UserServiceProdclass1 2 3 4 5 6 7 8 9 10 11 12 13 14package com.duotify.sbprofile1.services; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; @Component @Profile("!dev") public class UserServiceProd { @Bean public UserService getUserService() { return new UserService("Prod"); } }This
UserServiceDevwill only be executed by Spring when the non-devprofile is enabled. -
Modify the
HomeControllerand inject theUserServiceservice via “constructive”1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28package com.duotify.sbprofile1.controllers; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import com.duotify.sbprofile1.services.UserService; @RestController public class HomeController { @Value("${spring.profiles.active}") private String myProfile; @Value("${my.name}") private String myName; private UserService svc; public HomeController(UserService svc) { this.svc = svc; } @GetMapping("/") public String home() { return "Hello World: " + this.svc.getName(); } } -
Modify
pom.xmland add two more<profile>definitions -
Testing
Remember that we now have
5profiles, namelydefault,dev8,dev9,devandprod.Try to specify Profile
dev.1mvn clean spring-boot:run -PdevTry to specify Profile
prod.1mvn clean spring-boot:run -Pprod
Another practical example can be found in the example provided here.
Because Maven Profiles are so extensive, there are many more uses that can be found in the Guide to Maven Profiles.
Reference https://blog.miniasp.com/post/2022/09/21/Mastering-Spring-Boot-Profiles