Unlock the Full Power of Spring’s @Value: Tips, Tricks, and Common Pitfalls
This article provides a comprehensive guide to Spring’s @Value annotation, covering basic usage, property naming, handling Unicode and encoding issues, default values, static fields, arrays, collections, EL expressions, bean injection, and the differences between ${} and #{} syntax, with practical code examples and solutions to common problems.
Preface
For Java developers, the Spring framework is familiar, offering rich APIs for daily work. The @Value annotation is a useful but often overlooked feature for injecting system property values.
1. Starting with an Example
In a @Service class, a property can be injected as follows:
@Service
public class UserService {
@Value("${susan.test.userName}")
private String userName;
public String test() {
System.out.println(userName);
return userName;
}
}The property name must be wrapped in ${} and defined in applicationContext.properties:
# Example
susan.test.userName=\u5f20\u4e09If the property name in @Value does not match the one in the properties file, the application fails to start.
2. Property Names
When using @ConfigurationProperties, the field name can differ from the property name as long as the prefix is the same. For example:
@Configuration
@ConfigurationProperties(prefix = "susan.test")
@Data
public class MyConfig {
private String userName;
}In the properties file the key can be susan.test.user-name (kebab‑case) while the field is userName. Spring maps them automatically, but this flexibility does not apply to @Value; the names must be identical.
3. Encoding Issues
Chinese characters in .properties files are often stored as Unicode escapes (e.g., \u5f20\u4e09) because Spring reads them with ISO-8859-1, causing garbled output.
Solutions:
Manually convert the ISO‑8859‑1 bytes to UTF‑8.
Use @PropertySource with an encoding attribute (not applicable to @Value).
Store the value as a Unicode escape.
Example of manual conversion:
@Service
public class UserService {
@Value(value = "${susan.test.userName}")
private String userName;
public String test() {
String userName1 = new String(userName.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
return userName1;
}
}Using Unicode escapes avoids the need for conversion code.
4. Default Values
Provide a default by appending : inside the placeholder:
@Value(value = "${susan.test.userName:susan}")
private String userName;If the property is missing, the field receives susan. An empty default can be specified with ${property:}.
5. Static Variables
Directly annotating a static field with @Value results in null. Use a setter method to assign the static variable:
@Service
public class UserService {
private static String userName;
@Value("${susan.test.userName}")
public void setUserName(String userName) {
UserService.userName = userName;
}
}6. Variable Types
6.1 Primitive Types
@Value supports all primitive types and their wrapper classes:
@Value("${susan.test.a:1}")
private byte a;
@Value("${susan.test.b:100}")
private short b;
@Value("${susan.test.c:3000}")
private int c;
@Value("${susan.test.d:4000000}")
private long d;
@Value("${susan.test.e:5.2}")
private float e;
@Value("${susan.test.f:6.1}")
private double f;
@Value("${susan.test.g:false}")
private boolean g;
@Value("${susan.test.h:h}")
private char h;6.2 Arrays
Arrays are injected using comma‑separated values:
@Value("${susan.test.array:1,2,3,4,5}")
private int[] array;Note that spaces are removed, so 1 2 3 becomes 123.
6.3 Collections
List
Inject a List via an EL expression:
@Value("#{'${susan.test.list}'.split(',')}")
private List<String> list;Properties file:
susan.test.list=10,11,12,13Set
@Value("#{'${susan.test.set}'.split(',')}")
private Set<String> set;To provide an empty default, use the empty check:
@Value("#{'${susan.test.set:}'.empty ? null : '${susan.test.set:}'.split(',')}")
private Set<String> set;Map
@Value("#{${susan.test.map}}")
private Map<String, String> map;Properties file example:
susan.test.map={"name":"苏三","age":"18"}7. Advanced EL Usage
7.1 Bean Injection
Inject a bean directly with EL:
@Value("#{roleService}")
private RoleService roleService;7.2 Accessing Bean Members
Inject constants, fields, methods, and static methods:
@Value("#{roleService.DEFAULT_AGE}")
private int myAge;
@Value("#{roleService.id}")
private int id;
@Value("#{roleService.getRoleName()}")
private String myRoleName;
@Value("#{roleService.getParentId()}")
private String myParentId;7.3 Static Classes
Use T() to call static members:
@Value("#{T(java.io.File).separator}")
private String path;
@Value("#{T(java.lang.Math).random()}")
private double randomValue;7.4 Logical Operations
Combine values, perform conditionals, and ternary expressions:
@Value("#{roleService.roleName + '' + roleService.DEFAULT_AGE}")
private String combined;
@Value("#{roleService.DEFAULT_AGE > 16 and roleService.roleName.equals('苏三')}")
private boolean condition;
@Value("#{roleService.DEFAULT_AGE > 16 ? roleService.roleName : '苏三'}")
private String ternaryResult;8. Difference Between ${} and #{}
${}retrieves values from configuration files, optionally providing defaults with :. Missing properties without defaults cause startup failures. #{} evaluates Spring EL expressions, allowing bean injection, static method calls, and complex logic.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
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.
