Backend Development 20 min read

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.

macrozheng
macrozheng
macrozheng
Unlock the Full Power of Spring’s @Value: Tips, Tricks, and Common Pitfalls

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:

<code>@Service
public class UserService {

    @Value("${susan.test.userName}")
    private String userName;

    public String test() {
        System.out.println(userName);
        return userName;
    }
}
</code>

The property name must be wrapped in

${}

and defined in

applicationContext.properties

:

<code># Example
susan.test.userName=\u5f20\u4e09
</code>

If 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:

<code>@Configuration
@ConfigurationProperties(prefix = "susan.test")
@Data
public class MyConfig {
    private String userName;
}
</code>

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:

<code>@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;
    }
}
</code>

Using Unicode escapes avoids the need for conversion code.

4. Default Values

Provide a default by appending

:

inside the placeholder:

<code>@Value(value = "${susan.test.userName:susan}")
private String userName;
</code>

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:

<code>@Service
public class UserService {
    private static String userName;

    @Value("${susan.test.userName}")
    public void setUserName(String userName) {
        UserService.userName = userName;
    }
}
</code>

6. Variable Types

6.1 Primitive Types

@Value supports all primitive types and their wrapper classes:

<code>@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;
</code>

6.2 Arrays

Arrays are injected using comma‑separated values:

<code>@Value("${susan.test.array:1,2,3,4,5}")
private int[] array;
</code>

Note that spaces are removed, so

1 2 3

becomes

123

.

6.3 Collections

List

Inject a

List

via an EL expression:

<code>@Value("#{'${susan.test.list}'.split(',')}")
private List<String> list;
</code>

Properties file:

<code>susan.test.list=10,11,12,13
</code>

Set

<code>@Value("#{'${susan.test.set}'.split(',')}")
private Set<String> set;
</code>

To provide an empty default, use the

empty

check:

<code>@Value("#{'${susan.test.set:}'.empty ? null : '${susan.test.set:}'.split(',')}")
private Set<String> set;
</code>

Map

<code>@Value("#{${susan.test.map}}")
private Map<String, String> map;
</code>

Properties file example:

<code>susan.test.map={"name":"苏三","age":"18"}
</code>

7. Advanced EL Usage

7.1 Bean Injection

Inject a bean directly with EL:

<code>@Value("#{roleService}")
private RoleService roleService;
</code>

7.2 Accessing Bean Members

Inject constants, fields, methods, and static methods:

<code>@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;
</code>

7.3 Static Classes

Use

T()

to call static members:

<code>@Value("#{T(java.io.File).separator}")
private String path;

@Value("#{T(java.lang.Math).random()}")
private double randomValue;
</code>

7.4 Logical Operations

Combine values, perform conditionals, and ternary expressions:

<code>@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;
</code>

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.

JavaconfigurationSpring@ValueEL Expressions
macrozheng
Written by

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.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.