skip to content

@ConfigurationProperties & relaxed binding

@ConfigurationProperties binds a whole group of properties into a typed object, with relaxed naming so an environment variable and a kebab-case key reach the same field. Interviewers contrast it with @Value to see whether you group related settings or scatter them.

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

questions

5

What is @ConfigurationProperties and how does it differ from @Value?

level: juniorimportance: must knowfreq 78%

answer

  1. group vs single value
  2. prefix + type-safe bean
  3. @Value = one placeholder, no relaxed binding
  4. must register the bean
  5. type conversion via Binder

basics

~10 s

@ConfigurationProperties binds a whole group of external properties (from application.yml/properties/env) onto the fields of a POJO in a type-safe way. @Value injects a single property value into one field using a placeholder expression.

solid answer

~40 s

@ConfigurationProperties maps a tree of external configuration (prefixed keys from application.yml, .properties, environment variables) onto a strongly-typed Java bean, converting types and supporting nested objects, lists and maps. You bind once per group and get compile-time-friendly, testable config. @Value injects one value at a time via a SpEL/placeholder string like ${server.port}, with no relaxed binding, no nested-object support, and no built-in validation. Use @ConfigurationProperties for cohesive groups of settings (recommended by Spring Boot); use @Value for a single, occasionally-computed value. To activate a @ConfigurationProperties bean you either annotate it and register with @EnableConfigurationProperties, put @Component on it, or let @ConfigurationPropertiesScan discover it.

code

java · 22 lines
java
@ConfigurationProperties(prefix = "app.mail")
public class MailProperties {
    private String host;
    private int port = 25;
    private List<String> bcc = new ArrayList<>();

    public String getHost() { return host; }
    public void setHost(String host) { this.host = host; }
    public int getPort() { return port; }
    public void setPort(int port) { this.port = port; }
    public List<String> getBcc() { return bcc; }
    public void setBcc(List<String> bcc) { this.bcc = bcc; }
}

@Configuration
@EnableConfigurationProperties(MailProperties.class)
class MailConfig {
    @Bean
    MailSender sender(MailProperties props) {
        return new SmtpMailSender(props.getHost(), props.getPort());
    }
}

go deeper

for a junior

Know it's type-safe group binding by prefix vs @Value's single-value placeholder.

for a middle

Explain activation options and the relaxed-binding/validation/nested differences from @Value.

for a senior

Discuss the Binder, conversion service, and when each approach is architecturally appropriate.

for a principal

Frame config as a bounded, validated, testable contract; standardize on @ConfigurationProperties and metadata for the whole codebase.

## The problem it solves Applications read settings from *external configuration*: `application.properties`/`application.yml`, environment variables, command-line args, etc. Spring exposes all of these through the `Environment`. You could pull each value out one by one, but that scatters config all over the code and gives no type safety. ## @ConfigurationProperties `@ConfigurationProperties` (package `org.springframework.boot.context.properties`) binds a *group* of external properties sharing a common `prefix` onto the fields of a Java/Kotlin bean. ```java @ConfigurationProperties(prefix = "app.mail") public class MailProperties { private String host; // binds app.mail.host private int port; // binds app.mail.port private List<String> bcc; // binds app.mail.bcc[0], [1], ... // getters/setters } ``` Given: ```yaml app: mail: host: smtp.example.com port: 587 bcc: [[email protected], [email protected]] ``` Spring instantiates the bean, walks its properties, and binds each one, performing **type conversion** (String -> int, List, Duration, DataSize, enums, etc.) via the `Binder` and the `ApplicationConversionService`. ## Activating the bean A `@ConfigurationProperties` class is *not* a bean by itself. You must register it one of these ways: 1. `@EnableConfigurationProperties(MailProperties.class)` on a `@Configuration` class. 2. Put `@Component` (or `@ConfigurationProperties` on a `@Bean` factory method). 3. Use `@ConfigurationPropertiesScan` to auto-discover all `@ConfigurationProperties`-annotated classes in given packages. ## @Value contrast `@Value("${server.port}")` injects **one** value using property placeholders (and can use SpEL, e.g. `@Value("#{systemProperties['x']}")`). Differences: - **Granularity**: one value vs. a whole group. - **Relaxed binding**: `@ConfigurationProperties` supports it; `@Value` does **not** — the placeholder must match the exact property name. - **Nested/collection binding**: only `@ConfigurationProperties`. - **Validation**: `@ConfigurationProperties` supports JSR-303 `@Validated`; `@Value` does not (natively). - **Metadata**: `@ConfigurationProperties` participates in IDE metadata (`spring-configuration-metadata.json`). ## When to use which Use `@ConfigurationProperties` for cohesive configuration (recommended default in Spring Boot). Use `@Value` for a single standalone value or when you need a small SpEL computation. ## Gotchas - Forgetting to register the bean -> nothing binds, all fields null/default. - With classic (setter) binding you need setters; missing setters silently skip fields. - `@Value` cannot bind a list/map from a single property cleanly.

  • How do you make a @ConfigurationProperties class an actual Spring bean?
    Register it via @EnableConfigurationProperties(X.class), annotate it with @Component, expose it from an @Bean method, or enable @ConfigurationPropertiesScan to auto-discover it.
  • Can @Value use relaxed binding?
    No. @Value placeholders must match the exact property name; relaxed binding (kebab/camel/underscore equivalence) applies only to @ConfigurationProperties.

saying these in an interview costs you the question

  • Claiming @Value supports relaxed binding
  • Saying a @ConfigurationProperties class becomes a bean automatically without any registration
  • Thinking @Value can bind nested objects or lists like @ConfigurationProperties

context

open as a page

Explain relaxed binding: what property-name forms map to the same field?

level: middleimportance: must knowfreq 70%

basics

~10 s

Relaxed binding lets one bean field be filled from several property-name spellings — kebab-case, camelCase, snake_case, and UPPER underscore. So app.my-prop, app.myProp, app.my_prop and APP_MYPROP all bind to the same field.

open as a page

Compare @ConfigurationPropertiesScan, @EnableConfigurationProperties, and @Component for registering config beans.

level: middleimportance: should knowfreq 48%

basics

~10 s

@EnableConfigurationProperties(X.class) registers specific classes. @ConfigurationPropertiesScan auto-discovers all @ConfigurationProperties classes in given packages. @Component makes one a bean via component scanning. All make the config bean available for injection; you pick one per class.

open as a page

How does constructor binding work and how does it enable immutable @ConfigurationProperties?

level: seniorimportance: should knowfreq 55%

basics

~20 s

Bind values through the constructor instead of setters, so fields can be final and the config object is immutable. In Spring Boot 3 a single non-default constructor triggers constructor binding automatically; you no longer need setters.

open as a page

When would you use @Value with SpEL, and what are its limits versus @ConfigurationProperties?

level: seniorimportance: should knowfreq 45%

basics

~10 s

Use @Value for a single value, optionally computed with SpEL (#{...}) or defaulted (${prop:default}). Its limits: no relaxed binding, no nested/collection binding, no built-in validation, and it resolves eagerly per injection point.

open as a page