2.9 Configuration Binding (@ConfigurationProperties)
Use @ConfigurationProperties to bind typed and validated configuration from application.yml instead of many @Value fields. This gives clearer structure and better IDE autocomplete/validation.
Reference: Spring Boot 3.2.x
1. Basic Usage
# application.yml
app:
mail:
host: smtp.example.com
port: 587
security:
jwt-secret: my-secret
token-validity: 3600
@Configuration
@ConfigurationProperties(prefix = "app")
@Validated
@Getter
@Setter
public class AppProperties {
private final Mail mail = new Mail();
private final Security security = new Security();
@Getter
@Setter
public static class Mail {
private String host = "localhost";
private int port = 25;
}
@Getter
@Setter
public static class Security {
@NotBlank
private String jwtSecret;
@Min(60)
private long tokenValidity = 3600;
}
}
- prefix: Top-level key in yaml (
app) - @Validated + Bean Validation enables startup-time validation (build fails on missing required values)
2. Enabling Scan
Register with @EnableConfigurationProperties(AppProperties.class) or annotate the class with @Component. Spring Boot auto-scans classes annotated with @ConfigurationProperties, so @Configuration alone is usually sufficient.
3. Profile-Specific Values
# application-dev.yml
app:
mail:
host: mailhog
port: 1025
---
# application-prod.yml
app:
mail:
host: ${MAIL_HOST}
port: ${MAIL_PORT:587}
${ENV_VAR}: Environment variable${ENV_VAR:default}: Environment variable with default value
4. Constructor Binding (Immutable)
Since Spring Boot 2.2+, you can bind via constructor, making fields final for immutable config.
@ConfigurationProperties(prefix = "app.mail")
@ConstructorBinding // Can be omitted in Boot 3.x if there is only one constructor
@Getter
public class MailProperties {
private final String host;
private final int port;
public MailProperties(String host, int port) {
this.host = host;
this.port = port;
}
}
5. Spring Boot Config File Loading Order and Priority
Application config (application.properties / application.yml) is loaded from multiple locations; later sources override earlier ones for the same key. Higher priority wins.
5.1 Config Search Paths (higher priority first)
Spring Boot looks for application.properties / application.yml (and application-{profile}.properties etc.) in this order. Lower number = higher priority.
| Priority | Location | Note |
|---|---|---|
| 1 | Current directory /config | ./config/application.yml |
| 2 | Current directory | ./application.yml |
| 3 | Classpath /config | classpath:/config/application.yml |
| 4 | Classpath root | classpath:/application.yml (e.g. src/main/resources) |
- When running jar: Current directory and ./config override classpath, so you can place application.yml or config/application.yml next to the jar to override packaged defaults.
5.2 Profile-Specific vs Common File
- application.yml: Common; loaded without profile.
application-{profile}.yml: Loaded when that profile is active (e.g. application-dev.yml, application-prod.yml).
Override order (same key; later wins):
- application.yml (common)
application-{profile}.yml(active profile)
So application-prod.yml overrides application.yml.
5.3 External Config Priority (summary)
For the same key, Spring Boot applies (higher priority wins):
- Command line arguments —
--server.port=8081 - SPRING_APPLICATION_JSON (JSON in env var / system property)
- ServletConfig / ServletContext (web environment)
- JNDI
- Java system properties —
-Dserver.port=8081 - OS environment variables
- RandomValuePropertySource (
random.*) application-{profile}.ymloutside jarapplication-{profile}.ymlinside jar- application.yml outside jar
- application.yml inside jar
- @PropertySource
- Defaults (SpringBootApplication defaults, etc.)
In practice: defaults in jar application.yml, overrides via application-{profile}.yml or environment variables / command line.
5.4 Summary
- Path order:
./config/>./>classpath:/config/>classpath:/ - File type:
application-{profile}.ymloverridesapplication.ymlfor the same key. - External override: Command line and env vars override files, so secrets and ports can be supplied at deploy time.
6. List / Map
app:
allowed-hosts:
- api.example.com
- admin.example.com
features:
new-ui: true
beta: false
private List<String> allowedHosts = new ArrayList<>();
private Map<String, Boolean> features = new HashMap<>();
Use environment variables or Vault for secrets and reference them with ${VAR} in properties. See 5. Config File Loading Order and Priority to see which value wins when multiple sources define the same key.