skip to content

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

level: middleimportance: should knowfreq 48%

answer

  1. Enable = explicit list
  2. Scan = auto-discover packages
  3. @Component = setter-only, discouraged
  4. @Bean method for third-party objects
  5. avoid double registration

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.

solid answer

~40 s

There are three ways to turn a @ConfigurationProperties POJO into an injectable bean. @EnableConfigurationProperties(MyProps.class), placed on a @Configuration class, explicitly registers named classes and works with constructor binding. @ConfigurationPropertiesScan (often on the main class) scans base packages and auto-registers every @ConfigurationProperties-annotated type, so you don't list them — also works with constructor binding and is the modern default. @Component (plus @ConfigurationProperties) uses ordinary component scanning, but only supports setter binding, not constructor binding, and mixes config with regular bean semantics. Best practice: keep config classes annotation-only and register via @ConfigurationPropertiesScan or @EnableConfigurationProperties, reserving @Component for real components. Whichever you choose, don't register the same class two ways or you risk a duplicate-bean conflict.

code

java · 13 lines
java
// Modern default: scan + constructor binding
@SpringBootApplication
@ConfigurationPropertiesScan
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

@ConfigurationProperties(prefix = "app.mail")
public record MailProperties(String host, int port) {}
// No @Component, no @EnableConfigurationProperties needed —
// @ConfigurationPropertiesScan discovers it.

go deeper

for a junior

Know the three registration options exist and each yields an injectable bean.

for a middle

Contrast explicit vs scan vs component, and the setter-only limitation of @Component.

for a senior

Recommend scan + constructor binding; handle third-party binding via @Bean methods; avoid duplicate registration.

for a principal

Standardize a single registration convention org-wide to keep config discoverable and metadata-complete.

## Why registration is needed Annotating a class with `@ConfigurationProperties` describes *how to bind* it, but does not create a bean. You must register it so Spring instantiates it, binds properties, and makes it injectable. ## Option 1 — @EnableConfigurationProperties ```java @Configuration @EnableConfigurationProperties({MailProperties.class, PoolProperties.class}) class AppConfig {} ``` - **Explicit**: you list exactly which classes to register. - Works with **setter and constructor** binding. - Good when you want tight control or the class lives outside scanned packages. ## Option 2 — @ConfigurationPropertiesScan ```java @SpringBootApplication @ConfigurationPropertiesScan("com.example.config") public class App {} ``` - Scans the given base packages (defaults to the annotated class's package) and **auto-registers all** `@ConfigurationProperties` types. - Works with **constructor binding** and is the ergonomic modern choice — no per-class listing. - Note: `@SpringBootApplication` does **not** enable this by default; you add `@ConfigurationPropertiesScan` yourself. ## Option 3 — @Component (+ @ConfigurationProperties) ```java @Component @ConfigurationProperties(prefix = "app.mail") public class MailProperties { /* setters */ } ``` - Picked up by normal component scanning. - **Only setter binding** — constructor binding is *not* supported this way. - Blurs the line between config holder and regular bean; generally discouraged for pure config. ## @Bean method variant You can also put `@ConfigurationProperties(prefix=...)` on an `@Bean` factory method to bind an externally-created object (e.g. a third-party class you don't own): ```java @Bean @ConfigurationProperties(prefix = "app.datasource") DataSource dataSource() { return DataSourceBuilder.create().build(); } ``` ## Gotchas - **Double registration**: annotating a class `@Component` *and* passing it to `@EnableConfigurationProperties` can cause a duplicate-bean error. - Constructor-bound classes **must not** be `@Component`. - `@ConfigurationPropertiesScan` scanning the wrong package silently registers nothing. - Beans are named like `<prefix>-<fully.qualified.ClassName>` (a special convention), not the usual camelCase — usually irrelevant since you inject by type. ## Recommendation Use `@ConfigurationPropertiesScan` (or explicit `@EnableConfigurationProperties`) with immutable constructor-bound classes; avoid `@Component` for config.

  • Does @SpringBootApplication enable @ConfigurationPropertiesScan automatically?
    No. You must add @ConfigurationPropertiesScan yourself (or use @EnableConfigurationProperties); otherwise annotated config classes aren't registered.
  • How would you bind properties onto a third-party class you can't annotate?
    Put @ConfigurationProperties(prefix=...) on an @Bean factory method that creates the object; Spring binds the returned instance.

saying these in an interview costs you the question

  • Claiming @SpringBootApplication auto-enables @ConfigurationPropertiesScan
  • Saying @Component supports constructor binding
  • Registering a class both as @Component and via @EnableConfigurationProperties without expecting a conflict

context