What is the difference between @Value and @ConfigurationProperties?
In Spring Boot, both `@Value` and `@ConfigurationProperties` are used to inject externalized configuration properties into your application. While they serve a similar fundamental purpose, they are designed for different use cases and offer distinct advantages.
Understanding @Value
@Value is a core Spring Framework annotation used to inject single property values directly into fields, constructor parameters, or method parameters. It leverages Spring Expression Language (SpEL) to resolve property placeholders.
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class MyService {
@Value("${app.name}")
private String appName;
@Value("${app.version:1.0.0}")
private String appVersion;
public void displayInfo() {
System.out.println("App Name: " + appName);
System.out.println("App Version: " + appVersion);
}
}
Understanding @ConfigurationProperties
@ConfigurationProperties is a Spring Boot specific annotation used to bind a group of related properties from application configuration files (like application.properties or application.yml) to a Java object (POJO). It promotes strong type-safety and better organization for complex configurations.
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
@ConfigurationProperties(prefix = "app")
public class AppProperties {
private String name;
private String version = "1.0.0"; // Default value
private List<String> environments;
// Getters and Setters
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public List<String> getEnvironments() {
return environments;
}
public void setEnvironments(List<String> environments) {
this.environments = environments;
}
}
# application.properties
app.name=MySpringBootApp
app.version=2.1.0
app.environments[0]=dev
app.environments[1]=prod
Key Differences
| Feature | @Value | @ConfigurationProperties |
|---|---|---|
| Purpose | Injects single property values. | Binds a group of related properties to a POJO. |
| Usage | Used on fields, constructor parameters, or method parameters. | Used on a class level (POJO). |
| Granularity | Fine-grained (one property at a time). | Coarse-grained (a whole group of properties). |
| Type Safety | Limited type-safety; conversion errors are runtime. Requires manual casting or SpEL type conversion. | Strongly type-safe; properties are bound to fields of appropriate types. IDEs can detect issues at compile-time. |
| Validation | Requires explicit `@Validated` and often SpEL for complex validation. | Supports JSR-303 (Jakarta Bean Validation) annotations directly on fields within the POJO (`@NotNull`, `@Min`, etc.). |
| Binding | Direct string injection, potentially requiring explicit type conversion. | Sophisticated binding mechanism supporting nested objects, collections (lists, maps), and durations/data sizes. |
| Default Values | Provided directly in the SpEL expression (e.g., `${prop:defaultValue}`). | Can be set as initial field values in the POJO or via constructor arguments. |
| IDE Support | Limited autocompletion for property names. | Excellent autocompletion and hints due to metadata generation (with `spring-boot-configuration-processor`). |
| Use Cases | Simple, ad-hoc injection of a few isolated properties. | Managing complex, structured configurations, especially when properties have a common prefix. |
When to Use Which
- Use
@Valuewhen: - You need to inject a single, isolated property value into a field or method parameter.
- The property is simple (e.g., a string, integer, boolean) and doesn't belong to a larger, related group.
- You need to use SpEL for more complex value resolution or default values.
- Use
@ConfigurationPropertieswhen: - You have a group of related configuration properties (e.g., database connection details, external service settings).
- You want strong type-safety, robust validation, and better IDE support for your configuration.
- Your configuration involves complex types like lists, maps, nested objects, durations, or data sizes.
- You want to promote a clean, POJO-based approach to your application's configuration, making it more maintainable and readable.