How does Spring Boot manage environment properties?
Spring Boot provides a robust and flexible mechanism for managing environment properties, allowing applications to externalize configuration. This means you can run the same application code in different environments (development, test, production) by simply changing the configuration without repackaging the application. This guide explores the various ways Spring Boot manages and prioritizes these properties.
Overview of Externalized Configuration
Spring Boot applications are designed for externalized configuration, enabling you to use the same compiled code across multiple environments. You can provide configuration using property files, YAML files, environment variables, command-line arguments, and more. The framework's ConfigurableEnvironment plays a central role, abstracting the underlying property sources and providing a consistent API to access properties.
Property Sources and Order of Precedence
Spring Boot loads properties from various sources and consolidates them into a unified Environment. When a property is defined in multiple sources, Spring Boot applies a specific order of precedence, with higher-priority sources overriding lower-priority ones. This allows for fine-grained control over configuration values.
- Devtools global settings properties (when active).
@TestPropertySourceannotations on your tests.- Properties attribute on your tests (e.g.,
@SpringBootTest(properties = "a=b")). - Command-line arguments (e.g.,
--server.port=8081). - Properties from
SPRING_APPLICATION_JSON(inline JSON in an environment variable). - ServletConfig init parameters.
- ServletContext init parameters.
- JNDI attributes from
java:comp/env. - JVM system properties (
System.getProperties()). - Operating system environment variables.
RandomValuePropertySourceforrandom.*properties.- Application-specific properties outside your packaged JAR (e.g.,
application-{profile}.properties,application.propertiesin the current directory). - Application-specific properties inside your packaged JAR (e.g.,
application-{profile}.properties,application.propertiesin the classpath). @PropertySourceannotations on your@Configurationclasses.- Default properties (specified by
SpringApplication.setDefaultProperties).
Common Configuration Files
The most common way to define properties is through application.properties or application.yml files, typically located in the src/main/resources directory. YAML files offer a more human-readable and structured format.
Example application.properties:
server.port=8080
spring.application.name=my-spring-app
my.custom.property=Hello from properties
Example application.yml:
server:
port: 8080
spring:
application:
name: my-spring-app
my:
custom:
property: Hello from YAML
Profile-Specific Properties
Spring Boot supports profile-specific properties, allowing you to define different configurations for different environments (e.g., dev, test, prod). You can create files like application-dev.properties or application-prod.yml. The active profile can be set using spring.profiles.active property.
Example application-dev.properties:
server.port=8081
my.custom.property=Hello from Development
To activate this profile, you can use a command-line argument: --spring.profiles.active=dev or an environment variable SPRING_PROFILES_ACTIVE=dev.
Command-Line Arguments and Environment Variables
Command-line arguments (prefixed with --) and operating system environment variables provide a simple way to override properties at runtime. These have a higher precedence than properties defined in application.properties/yml files.
Example using command-line arguments to override the server port:
java -jar my-spring-app.jar --server.port=9000
Spring Boot also supports relaxed binding for environment variables, meaning SERVER_PORT, SERVER_PORT, or server_port can all map to server.port.
Accessing Properties in Your Application
Spring Boot provides several ways to access configured properties within your application code.
1. Using the @Value annotation for individual properties:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class MyService {
@Value("${my.custom.property:Default Value}")
private String customProperty;
public void doSomething() {
System.out.println("Custom Property: " + customProperty);
}
}
2. Using the Environment object to programmatically access properties:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
@Component
public class MyAnotherService {
@Autowired
private Environment env;
public void doAnotherThing() {
String appName = env.getProperty("spring.application.name");
System.out.println("Application Name: " + appName);
}
}
3. Using @ConfigurationProperties for type-safe externalized configuration:
This approach binds an entire branch of properties to a Java object, providing strong typing, validation, and documentation.
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "app.settings")
public class AppSettings {
private String name;
private int maxUsers;
private String apiKey;
// Getters and Setters
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getMaxUsers() {
return maxUsers;
}
public void setMaxUsers(int maxUsers) {
this.maxUsers = maxUsers;
}
public String getApiKey() {
return apiKey;
}
public void setApiKey(String apiKey) {
this.apiKey = apiKey;
}
}
Corresponding application.yml or application.properties:
app:
settings:
name: My Awesome App
max-users: 1000
api-key: some-secret-key-123
Conclusion
Spring Boot's property management system is highly flexible and powerful, designed to make externalized configuration straightforward. By understanding the various property sources and their order of precedence, developers can effectively manage application settings across different environments, enhancing portability and maintainability. Whether using simple .properties files, structured YAML, or advanced @ConfigurationProperties, Spring Boot offers the right tool for every configuration need.