skip to content

@Value Injection

@Value binds a resolved placeholder, a default, or a SpEL expression into a field or parameter, converting the literal on the way in. Interviewers use it to check that you know the placeholder syntax and where defaults belong.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

questions

5

How does @Value with a ${...} placeholder work, and how do you supply a default when the property is missing?

level: juniorimportance: must knowfreq 85%

answer

  1. ${prop:default} = default when absent
  2. PropertySourcesPlaceholderConfigurer resolves it
  3. Missing + no default → Could not resolve placeholder
  4. String converted via ConversionService
  5. Not on static fields

basics

~10 s

@Value("${my.prop}") injects the value of property my.prop from the environment into a field or parameter. Use ${my.prop:fallback} to supply a default when the property is not set.

solid answer

~40 s

@Value("${prop}") tells Spring to resolve the placeholder ${prop} against the Environment (application.properties/yaml, env vars, system properties) and inject the resolved value into the annotated field, constructor param, or method arg. Resolution is done by a PropertySourcesPlaceholderConfigurer, which Spring Boot auto-registers. Syntax ${prop:default} supplies a default used only when the property is absent; ${prop:} yields an empty string. If a placeholder has no property and no default, Spring throws IllegalArgumentException: Could not resolve placeholder at startup. The injected text is converted to the target type (int, boolean, Duration, etc.) by the ConversionService. Prefer constructor injection so the field is final and validated at construction time.

code

java · 16 lines
java
@Component
public class MailSettings {
    private final String host;
    private final int port;
    private final boolean tls;

    // Constructor injection: values resolved before the body runs
    public MailSettings(
            @Value("${mail.host}") String host,                 // required
            @Value("${mail.port:25}") int port,                 // default 25, converted to int
            @Value("${mail.tls:true}") boolean tls) {           // default true, converted to boolean
        this.host = host;
        this.port = port;
        this.tls = tls;
    }
}

go deeper

for a junior

Know ${prop} injects a property and ${prop:default} adds a fallback.

for a middle

Explain who resolves placeholders (PropertySourcesPlaceholderConfigurer), the fail-fast on missing property, and String→type conversion.

for a senior

Contrast constructor vs field injection timing, empty-default semantics ${prop:}, and when to switch to @ConfigurationProperties.

for a principal

Discuss configuration strategy: @Value for a few flags vs typed binding; startup validation; and the plain-Spring requirement to register the configurer as a static bean.

## What @Value does `@Value` is a Spring annotation that injects a computed value into a bean member. When its string starts with `${...}` it is a *property placeholder*: Spring looks up the named property in the `Environment` and substitutes the resolved value. ## Where properties come from The `Environment` aggregates ordered `PropertySource`s: - `application.properties`/`application.yml`, - OS environment variables, - JVM `-D` system properties, - command-line args, etc. (The exact ordering/precedence is a separate topic.) `@Value` only asks for the *final resolved* value. ## Who resolves placeholders A `PropertySourcesPlaceholderConfigurer` (a `BeanFactoryPostProcessor`) performs the `${...}` substitution on bean-definition values and `@Value` strings. In Spring Boot this bean is auto-registered; in plain Spring you must declare one (a `static @Bean` method) or placeholders won't be replaced and you'll see the literal `${...}` text. ## Defaults and missing properties **Defaults.** - `${prop:default}` uses `default` when `prop` is undefined. - `${prop:}` gives an empty string. - Defaults can themselves nest placeholders: `${prop:${fallback.prop}}`. **Missing property, no default.** Resolution fails fast: `IllegalArgumentException: Could not resolve placeholder 'prop' in value "${prop}"` during context startup. This is usually desirable — misconfiguration surfaces immediately. ## Type conversion The resolved value is always a String from the property source. Spring converts it to the target member type using the `ConversionService` (Boot's `ApplicationConversionService`) plus built-in `PropertyEditor`s: - `"8080"`→`int`, - `"true"`→`boolean`, - `"10s"`→`Duration`, - `"a,b,c"`→`List<String>`/`String[]`. ## Using it well **Where you can put it.** Fields, constructor parameters, `@Bean` method parameters, and setter/method parameters. It does **not** work on `static` fields. **When to use.** `@Value` is best for a small number of individual settings. For a group of related properties prefer `@ConfigurationProperties`, which binds a whole typed object, supports relaxed binding and validation, and is easier to test. **Gotcha.** Escaping: a literal `${` in a default needs care; and reading a `@Value` field inside the constructor of the *same* bean sees `null` for field injection because field injection happens after construction — use constructor-parameter `@Value` instead.

  • What happens at startup if mail.host is not defined anywhere and has no default?
    Context startup fails with IllegalArgumentException: Could not resolve placeholder 'mail.host'. This is fail-fast behavior.
  • Why prefer constructor @Value over field @Value?
    The value is available during construction (usable in the constructor body), the field can be final/immutable, and the class is easy to unit-test by passing values directly without Spring.

saying these in an interview costs you the question

  • Saying ${prop} evaluates SpEL — it's placeholder resolution, not SpEL
  • Thinking a missing property silently injects null instead of failing
  • Claiming @Value works on static fields
  • Believing you never need a PropertySourcesPlaceholderConfigurer even in plain (non-Boot) Spring

context

open as a page

What is the difference between @Value("${...}") and @Value("#{...}"), and can they be combined?

level: middleimportance: must knowfreq 75%

basics

~20 s

${...} is a property placeholder: it looks up a property in the Environment. #{...} is a SpEL expression that is evaluated (method calls, math, bean references). You can nest a placeholder inside SpEL, e.g. #{'${my.list}'.split(',')}.

open as a page

When should you choose @Value over @ConfigurationProperties for binding configuration, and what are the tradeoffs?

level: middleimportance: should knowfreq 60%

basics

~20 s

Use @Value for a few individual, unrelated settings or when you need SpEL. Use @ConfigurationProperties to bind a whole group of related properties into a typed object with relaxed binding, validation, and easy testing. @Value doesn't support relaxed binding or bean validation.

open as a page

When you inject a property string into a non-String type via @Value, how does Spring convert it, and what types work out of the box?

level: seniorimportance: should knowfreq 55%

basics

~20 s

Property values are Strings. Spring converts the injected String to the target type using the ConversionService (plus PropertyEditors). Out of the box it handles primitives, enums, Duration, DataSize, arrays/List/Set/Map from delimited text, and more. Register a custom Converter for unsupported types.

open as a page

What are the timing and placement gotchas of @Value: injecting into static fields, reading the value in a constructor, and using @Value inside a BeanFactoryPostProcessor?

level: principalimportance: nice to knowfreq 35%

basics

~20 s

@Value doesn't work on static fields. With field injection the value isn't set until after construction, so reading it in the constructor gives null — use constructor-param @Value instead. And placeholders may not resolve inside a BeanFactoryPostProcessor because it is created before the placeholder configurer runs.

open as a page