Mastering Spring @Value: From Basics to Advanced Techniques
This article explains how Spring Boot’s @Value annotation injects configuration values, covers basic usage, default values, nested properties, SpEL expressions, custom type converters, placeholder handling, custom meta‑annotations, and combining property placeholders for dynamic URLs, providing complete code examples.
1. Introduction
Spring's @Value annotation injects external configuration (e.g., from application.yml ) into bean fields, constructor parameters, or method parameters. It supports simple types, SpEL expressions, and default values, making it a convenient choice for straightforward configuration needs.
<code>@Value("${pack.title}")
private String title ;
</code>Corresponding YAML:
<code>pack:
title: xxxooo
</code>The above assigns title the value xxxooo . Type conversion is automatic, e.g., to LocalDate :
<code>@Value("${pack.date}")
private LocalDate date ;
</code> <code>pack:
date: 2024-07-27
</code>2. Advanced Usage
2.1 Default Value
If a property is missing, Spring Boot throws an exception. You can provide a default by appending a colon:
<code>@Value("${pack.version:}")
</code>or with an actual fallback value:
<code>@Value("${pack.version:1.0.0}")
</code>2.2 Nested Property
You can reference another property inside the default expression:
<code>@Value("${pack.title:${title}}")
private String title ;
</code>YAML example:
<code>title: xxxooo
pack:
date: 2024-07-27
</code>2.3 Using SpEL Expressions
Inject system properties:
<code>@Value("#{systemProperties['java.home']}")
private String javaHome ;
</code>Result example:
<code>D:\devsoft\jdk-21_windows-x64_bin\jdk-21.0.1</code>Inject other beans:
<code>@RestController
public class UserController {
@Value("#{us}")
private UserService us ;
@Override
public String toString() {
return "UserController [us=" + us + "]";
}
}
</code>Result:
<code>com.pack.UserService@54e1c68b</code>2.4 Custom Type Conversion
Register a custom converter:
<code>@Bean
public ConversionService conversionService() {
DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();
conversionService.addConverter(new StringToDateConverter());
return conversionService;
}
public class StringToDateConverter implements Converter<String, Date> {
public Date convert(String source) {
try {
return new SimpleDateFormat("yyyy-MM-dd").parse(source);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}
</code>Then:
<code>@Value("${pack.date}")
private Date productDate ;
</code>Result:
<code>Sat Jul 27 00:00:00 CST 2024</code>Note: In Spring Boot, using BeanFactoryPostProcessor is often recommended for such registrations.
2.5 Custom Default Behavior
Override placeholder handling to ignore unresolved placeholders:
<code>@Bean
public PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
PropertySourcesPlaceholderConfigurer pspc = new PropertySourcesPlaceholderConfigurer();
pspc.setIgnoreUnresolvablePlaceholders(true);
return pspc;
}
</code>When the property is absent, the expression itself is output:
<code>@Value("${pack.version}")
private String version ;
</code> <code>${pack.version}</code>You can also change the placeholder delimiters:
<code>pspc.setPlaceholderPrefix("&{");
pspc.setPlaceholderSuffix("}");
</code>2.6 Custom @Value Annotation
Create a meta‑annotation to reuse a specific property key:
<code>@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Value("${pack.url}")
public @interface PackValue {}
</code>Usage:
<code>@PackValue
private String url ;
</code>2.7 Combining ${} and #{}
Compose a value from multiple properties using SpEL:
<code>@Value("#{'${pack.baseURL}' + '/api/v' + '${app.version}'}")
private String url ;
</code>YAML:
<code>app:
version: 1.0
pack:
baseURL: https://www.pack.com
</code>Result:
<code>http://www.pack.com/api/v1.0</code>Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.