Spring @Value Annotation Guide Spring @Value Annotation Guide

Page content

This article demonstrate use of Spring @Value annotation with Primitives, Default value, Dates, List, Map, System Properties, Constructor Injection, Setter Injection, and Methods…

This annotation is used for injecting values into fields in Spring-managed beans and its value typically comes from property files (.properties and .yml files), system properties and environment variables.

1. Using @Value with Primitives

application.properties

course.title = "How to use Spring @Value annotation"
course.duration = 30
course.rating = 4.5
course.page_views = 1e+10
course.trending = true

We can set the values of primitive fields such as String, int, float, double and boolean from property file as below:-

@Value("${course.title}")
private String title;

@Value("${course.duration}")
private int duration;

@Value("${course.rating}")
private float rating;

@Value("${course.page_views}")
private double pageViews;

@Value("${course.trending}")
private boolean trending;


2. Using @Value with Default value

Default values can be provided for properties that might not be defined. In below example the property course.review is not defined so review field will be initialized with default value i.e. “No Reviews Yet”.

// @Value("${property: defaultValue}")
@Value("${course.review: No Reviews Yet}")
private String review;


3. Using @Value with Dates

application.properties

course.created_date = 2020-05-26

There is no direct support to initialize a LocalDate field using @Value annotation. We need to use SpEL (Spring Expression Language) to initialize LocalDate field by parsing a String property:

// SpEL expression used to initialize a Date
@Value("#{T(java.time.LocalDate).parse('${course.created_date}')}")
private LocalDate createdDate;


4. Using @Value with List

application.properties

course.tags = Java, Spring, Spring Boot, Annotation

Any property having comma separated values can be initialized as a List using @Value annotation in latest version of Spring.

// Comma separated property values auto initialize a List
@Value("${course.tags}")
private List<String> tags;

If you are using old version of Spring, require SpEL expression to initialize a List:

@Value("#{'${course.tags}'.split(',')}")
private List<String> tags;

SpEl expression can also be used to get specific value from comma separated values:

@Value("#{'${course.tags}'.split(',')[0]}")
private String firstTag;


5. Using @Value with Map

application.properties

course.keyword_count = { 'keyword1': '12', 'keyword2': '44', 'keyword3': '85', 'keyword4': '100'} 

Note: the keys and values in the property Map must be in single quotes.

We can initialize a Map using above property using SpEL expression inside @Value annotation

// SpEL expression used to initialize a Map
@Value("#{${course.keyword_count}}")
private Map<String, Integer> keywordCountMap;

If we need to get the value of a specific key in the Map, all we have to do is add the key’s name in the expression:
We can use any one out of these two ways:-

// way 1 - .key
@Value("#{${course.keyword_count}.keyword1}")
private Integer FirstKeywordCount;

// way 2 - ['key']
@Value("#{${course.keyword_count}['keyword2']}")
private Integer SecondKeywordCount;

If we’re not sure whether the Map contains a certain key, we should choose a safer expression that will not throw an exception but set the value to null when the key is not found:

@Value("#{${course.keyword_count}['unknownKey']}")
private Integer unknownKeywordCount;

We can also set default values for the properties or keys that might not exist:

@Value("#{${unknownMap : {key1: '1', key2: '2'}}}")
private Map<String, Integer> unknownMap;
	
@Value("#{${course.keyword_count}['unknownKey'] ?: 100}")
private Integer unknownKeyWithDefaultValue;

Map entries can also be filtered before injection. Let’s assume we need to get only those entries whose keyword count is greater than 50:

@Value("#{${course.keyword_count}.?[value > '50']}")
private Map<String, Integer> keywordCountMapFiltered;


6. Using @Value with System Properties

You can use @Value annotation for System properties similar to as they were defined in property file. Example of System Properties are as below

//UTF-8
@Value("${file.encoding}")
private String fileEncoding;

//Mac OS X
@Value("${os.name}")
private String osName;

// /Users/ashishkumarlahoti
@Value("${user.home}")
private String userHome

We can also use the @Value annotation to inject all current system properties:

@Value("#{systemProperties}")
private Map<String, String> systemPropertiesMap;

We can also use SpEL expressions to get the value from System Property Map:

// /Library/Java/JavaVirtualMachines/jdk1.8.0_211.jdk/Contents/Home/jre
@Value("#{systemProperties['java.home']}")
private String javaHome;

//Oracle Corporation
@Value("#{systemProperties['java.vendor']}")
private String javaVendor;

We can also initialize some default value if System property is not available:

@Value("#{systemProperties['unknown'] ?: 'Default Value'}")
private String unknownSystemProperty;


7. Using @Value with Constructor Injection

When we use the @Value annotation, we’re not limited to a field injection. We can also use it together with constructor injection.

Let’s see this in practice:

@Component
@PropertySource("classpath:values.properties")
public class PriorityProvider {
 
    private String priority;
 
    @Autowired
    public PriorityProvider(@Value("${priority:normal}") String priority) {
        this.priority = priority;
    }
 
    // getter setter
}

In the above example, we inject a priority directly into our PriorityProvider‘s constructor.

Note, we also provide a default value in case the property isn’t found.


8. Using @Value with Setter Injection

Similar to constructor injection, we can also use @Value with setter injection.

@Component
@PropertySource("classpath:values.properties")
public class CollectionProvider {
 
    private List<String> values = new ArrayList<>();
 
    @Autowired
    public void setValues(@Value("#{'${listOfValues}'.split(',')}") List<String> values) {
        this.values.addAll(values);
    }
 
    // getter setter
}

In the code above, we use the SpEL expression to inject a list of values into the setValues method.

9. Using @Value with Methods

When the @Value annotation is found on a method, Spring context will invoke it when all the spring configurations and beans are getting loaded. If the method has multiple arguments, then every argument value is mapped from the method annotation. If we want different values for different arguments then we can use @Value annotation directly with the argument.

@Value("Test")
public void printValues(String a, String b){
	System.out.println(a + " & " + b); // Test & Test
}

@Value("Test")
public void printOtherValues(String a, @Value("Another Test") String b){
	System.out.println(a + " & " + b); // Test & Another Test
}