@ConfigurationProperties
IntermediateBinds a whole hierarchy of properties to a strongly-typed POJO, supporting relaxed binding, JSR-303 validation, and IDE auto-completion.
Overview
@ConfigurationProperties is the preferred way to externalise and structure configuration in Spring Boot. While @Value injects a single property at a time, @ConfigurationProperties binds an entire group of related properties to a strongly-typed Java class. This gives you IDE auto-completion (with the annotation processor on the classpath), compile-time safety, relaxed binding (camelCase, kebab-case, UPPER_CASE all map to the same field), and first-class support for JSR-303 bean validation. It is the right tool for any configuration that has more than one or two values — e.g., database settings, S3 bucket details, external API endpoints.
Declaring & Using @ConfigurationProperties
Annotate a POJO with @ConfigurationProperties(prefix = "your.prefix") and register it as a bean. Spring Boot automatically binds every property under that prefix to the matching fields. Use @EnableConfigurationProperties or simply annotate the class with @Component / @ConfigurationPropertiesScan.
// application.yml
payment:
gateway-url: https://api.stripe.com/v1
api-key: sk_live_xxxx
timeout-seconds: 30
retry:
max-attempts: 3
back-off-ms: 500
// 1. Define the POJO
@ConfigurationProperties(prefix = "payment")
@Validated // enables JSR-303 validation on fields
public class PaymentProperties {
@NotBlank
private String gatewayUrl;
@NotBlank
private String apiKey;
@Min(1) @Max(120)
private int timeoutSeconds;
private Retry retry = new Retry(); // nested object
// getters + setters (or use a record in Boot 3.x)
public static class Retry {
private int maxAttempts = 3;
private long backOffMs = 500;
// getters + setters
}
}
// 2. Register (choose one approach)
@SpringBootApplication
@ConfigurationPropertiesScan // scans for all @ConfigurationProperties in package
public class App { }
// 3. Inject anywhere
@Service
@RequiredArgsConstructor
public class PaymentService {
private final PaymentProperties props;
// props.getGatewayUrl(), props.getRetry().getMaxAttempts(), etc.
}Relaxed Binding & Records (Boot 3+)
Spring Boot's relaxed binding means the property `gateway-url`, `GATEWAY_URL`, and `gatewayUrl` all bind to the same Java field `gatewayUrl`. This is critical for Kubernetes environments where config is often uppercase env vars. In Spring Boot 3.x (Java 17+), you can use an immutable Java record annotated with @ConfigurationProperties — no setters needed.
// Spring Boot 3+ — immutable record binding
@ConfigurationProperties(prefix = "payment")
public record PaymentProperties(
@NotBlank String gatewayUrl,
@NotBlank String apiKey,
@Min(1) int timeoutSeconds
) {}
// All of these bind to the same field (relaxed binding):
# application.properties
payment.gateway-url=... # kebab-case ✅
payment.gatewayUrl=... # camelCase ✅
PAYMENT_GATEWAY_URL=... # env var ✅ (Kubernetes ConfigMap / Secret)IDE Auto-Completion with spring-configuration-metadata
Add the annotation processor to get IDE auto-completion, documentation, and type hints for your custom properties — the same experience as Spring Boot's own properties.
<!-- Maven: generates META-INF/spring-configuration-metadata.json -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
// Gradle
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
// After adding this, IntelliJ / VS Code will show:
// - property key suggestions in application.yml
// - type hints (int, String, Duration)
// - Javadoc from the field's comment as descriptionKey Points to Remember
- 1@ConfigurationProperties binds a whole group of related properties to one POJO — much cleaner than multiple @Value annotations.
- 2Add @Validated to the properties class and JSR-303 annotations on fields — Spring Boot fails fast on startup if config is invalid.
- 3Relaxed binding maps kebab-case YAML, camelCase Java, and UPPERCASE_ENV_VARS to the same field automatically.
- 4Use a Java record (Boot 3+) for immutable, concise configuration properties without boilerplate getters/setters.
- 5Add spring-boot-configuration-processor (optional, annotationProcessor scope) to unlock IDE auto-completion for your custom properties.
- 6Nested objects are supported — group sub-settings in inner classes or nested records for clean hierarchies.
Interview Questions
Sign in to ask AriaWhat is the difference between @Value and @ConfigurationProperties?
How does relaxed binding work in Spring Boot?
How do you validate configuration properties at startup to fail fast on bad config?
How do you bind a list or map of values using @ConfigurationProperties?
What is the role of spring-boot-configuration-processor and when would you add it?
Ask Aria about @ConfigurationProperties
Your personal AI tutor — ask anything about this concept
Revision Status
Personal Notes
Sign in to save personal notes for this topic.
Discussion
Sign in to join the discussion.