Did it ever happen to you that after spending some time and gaining experience with a framework or a programming language, you learn things that would have made your programmer's life much easier if you had known them right from the start? You would have done things differently, more quickly, in a simpler, cleaner and more maintainable way?

I decided to write a series of posts about features and aspects of Spring Framework (the framework in which I spend most of my professional software development time) that I found useful (usually far later than I'd like to admit :) ), but which are often not covered in entry level guides and tutorials.

In this first post I would like to discuss the @Value annotation.

I started working with Spring framework since the 2.5 version. Later on, when 3.0 was released, JavaConfig became the part of the core framework along with the @Value that was part of it. I unfortunately didn't notice that improvement for quite some time, mostly because the projects I worked on relied on XML based config.

Here's what Spring javadocs say about @Value:

Annotation at the field or method/constructor parameter level that indicates a default value expression for the affected argument.

Typically used for expression-driven dependency injection. Also supported for dynamic resolution of handler method parameters, e.g. in Spring MVC.

A common use case is to assign default field values using "#{systemProperties.myProp}" style expressions.

Let's see how we can make use of it.

Assigning values from property files

This is likely the most common use case for @Value annotation. @Value allows us to easily inject a value from a property file to, for example, a bean's field or a constructor argument.

If we had a property file that looks like this:

app.name = My Excellent Application

Then we could use that property definition in, say, a controller using@Value("${propertyName}") syntax:

@Controller
public class HelloController {
	
	@Value("${app.name}")
	private String appName;

	@RequestMapping("/")
	@ResponseBody
	public String hello() {
		return "Hello from " + appName;
	}

}

The code in the example will read the property app.name from property file and inject it into appName field. The ${...} syntax is Spring's property placeholder syntax used in property placeholder replacement mechanism. If app.name is not defined, then an exception will be thrown. Which brings us to a less known fact about property placeholders - it's possible to set a default value for a property that Spring would use if the property is not defined. The syntax for default values in property placeholders is ${property:defaultValue}. You can read about it the javadocs for PlaceholderConfigurerSupport class. I find default values quite useful, especially in situations where a particular property of a bean is not likely to be changed in different environments and as such you don't want to introduce it needlessly into a property file, but still want to give yourself an option to change your mind later. If we were to modify our example to use a default value, it would look like this:

@Controller
public class HelloController {
	
	@Value("${app.name:My Excellent Application}")
	private String appName;

	@RequestMapping("/")
	@ResponseBody
	public String hello() {
		return "Hello from " + appName;
	}

}

Injecting a SpringEL dynamically evaluated value

Do you remember @Value's javadoc that was shown previously? It described a #{...} syntax rather than property replacement ${...} syntax that we used in our example. What's the difference? The #{...} syntax invokes Spring Expression Language (SpringEL) and evaluates the expression dynamically. For example we could obtain a value from the system settings:

@Value("#{systemSettings['user.region']}")
private String locale; 

The above expression works because systemSettings is a variable that's always available to SpringEL when it's invoked in this context (e.g. when configuring beans).

We may even inject a return value of a method of another bean:

@Value("#{'V1.0S' + migrationService.version}")
private String version;

In this example Spring will inject string "V1.0S" prepended to the return value of method getVersion() of a bean with name migrationService (all beans in Spring's context are available as variables in SpringEL).

To conclude,@Value annotation is indispensable asset when configuring your beans. When pursing convention-over-configuration style, default values for property placeholders used in@Value configs may come in handy. And finally, always keep on your mind that you can invoke SpringEL to help you to simplify scenarios that may otherwise require complex config or workarounds.


Did you find this article helpful? What is your favorite Spring feature? Do you have a related blog post? Feel welcome to leave feedback or comments below :)