What is @ConfigurationProperties, and how does it differ from @Value?
Quick Answer
@Value injects a single configuration property into a single field, using a SpEL/placeholder expression, with no built-in validation or grouping. @ConfigurationProperties binds an entire group of related, hierarchical properties (a prefix like app.mail.*) onto a strongly-typed POJO or record in one step, supporting nested objects, lists, relaxed binding (kebab-case/camelCase/etc. interchangeably), and integration with Bean Validation — making it the better choice for anything beyond a single, standalone value.
Detailed Answer
Both read values from application.properties/application.yml, but at very different granularity:
@Value injects a single property into a single field, via a placeholder expression (which also supports full SpEL):
@Component
class MailService {
@Value("${app.mail.host}")
private String host;
@Value("${app.mail.port:25}") // default value if not set
private int port;
}
This gets unwieldy fast for anything with more than a couple of related values — no grouping, no nested structure, no built-in validation.
@ConfigurationProperties binds an entire group of hierarchical properties onto a dedicated, strongly-typed class in one step:
app:
mail:
host: smtp.example.com
port: 587
recipients:
- alice@example.com
- bob@example.com
@ConfigurationProperties(prefix = "app.mail")
public record MailProperties(String host, int port, List<String> recipients) { }
@Configuration
@EnableConfigurationProperties(MailProperties.class) // or annotate MailProperties with @Component directly
class MailConfig { }
Advantages of @ConfigurationProperties over scattered @Value fields:
- Grouping and structure — nested objects, lists, and maps bind naturally, instead of one
@Valueper leaf property. - Relaxed binding —
app.mail.host,app.mail-host, andAPP_MAIL_HOST(environment variable form) all bind to the same property, letting the same configuration class work across.yml,.properties, and environment-variable-based configuration (common in containerized deployments) without code changes. - Validation support — combining it with
@Validatedand Bean Validation annotations (@NotBlank,@Min) lets Spring Boot fail fast at startup if required configuration is missing or malformed, rather than surfacing aNullPointerExceptiondeep in application logic later. - IDE tooling — Spring Boot can generate metadata (
spring-configuration-metadata.json) giving autocomplete and documentation for these properties in IDEs.
Rule of thumb: use @Value for a genuinely standalone, one-off property; use @ConfigurationProperties for anything with more than one or two related values, or anything you'd want validated at startup.