skip to content

What does PropertySourcesPlaceholderConfigurer do, and how does it relate to BeanFactoryPostProcessor?

level: middleimportance: should knowfreq 45%

answer

  1. resolves ${...} against Environment
  2. it IS a BeanFactoryPostProcessor
  3. PropertySources ordered, first match wins
  4. replaces legacy PropertyPlaceholderConfigurer
  5. Boot auto-configures; manual = static @Bean

basics

~10 s

It is a BeanFactoryPostProcessor that replaces ${...} placeholders in bean definitions with values from the Spring Environment (property files, env vars, system properties). It resolves them before beans are created.

solid answer

~40 s

PropertySourcesPlaceholderConfigurer is the standard BeanFactoryPostProcessor that resolves ${...} placeholders in bean definitions against the Environment's PropertySources — application.properties/yaml, OS environment variables, system properties, command-line args, in priority order. Because it is a BFPP, it rewrites the definitions before instantiation, so injected @Value("${...}") strings and XML placeholders arrive already resolved. It succeeded the older PropertyPlaceholderConfigurer, which read only its own local properties and ignored the Environment. In Spring Boot you almost never declare it — Boot auto-configures one (PropertySourcesPlaceholderConfigurer via PropertyPlaceholderAutoConfiguration). If you do declare it manually in a @Configuration class, the @Bean method must be static, because BFPPs are created very early — before the config class is enhanced.

code

java · 11 lines
java
@Configuration
public class PlaceholderConfig {

    // MUST be static: it is a BeanFactoryPostProcessor, created very early.
    @Bean
    public static PropertySourcesPlaceholderConfigurer propertyConfigurer() {
        PropertySourcesPlaceholderConfigurer c = new PropertySourcesPlaceholderConfigurer();
        c.setIgnoreUnresolvablePlaceholders(false); // fail fast on missing keys
        return c;
    }
}

go deeper

for a junior

Know it swaps ${...} for property values before beans are created.

for a middle

Explain it as a BFPP, the Environment/PropertySource precedence, and the :default syntax.

for a senior

Discuss the static @Bean requirement, ignoreUnresolvablePlaceholders, and multiple-configurer conflicts.

for a principal

Weigh @Value placeholders vs @ConfigurationProperties, and how Boot's PropertySource ordering drives config layering across environments.

## Purpose `PropertySourcesPlaceholderConfigurer` (package `org.springframework.context.support`) is a concrete `BeanFactoryPostProcessor` that performs **placeholder resolution**. It scans bean definitions for `${...}` tokens and replaces them with real values pulled from the Spring **`Environment`**. Example source values: ```properties # application.properties app.timeout=30 ``` ```java @Component class Client { Client(@Value("${app.timeout:10}") int timeoutSeconds) { ... } // resolved to 30 } ``` The `:10` after the key is a **default** used if the key is absent. ## Why it is a BeanFactoryPostProcessor Placeholders live inside **bean definitions** (property values, constructor args, `@Value` metadata). They must be resolved **before** the beans are instantiated so the real values are present at construction time. That is exactly the BFPP window: after definitions are loaded, before instantiation. So `PropertySourcesPlaceholderConfigurer` implements `BeanFactoryPostProcessor` and mutates the definitions in place. ## PropertySources and precedence The `Environment` holds an ordered list of `PropertySource`s. Resolution walks them in order and the **first match wins**. Typical Spring Boot order (highest first): command-line args, `SPRING_APPLICATION_JSON`, OS environment variables, system properties, profile-specific `application-{profile}.properties/yml`, then `application.properties/yml`. This is why the same key in an env var overrides the one in a properties file. ## vs the legacy PropertyPlaceholderConfigurer The older `PropertyPlaceholderConfigurer` predates the unified `Environment`/`PropertySource` abstraction (Spring 3.1). It resolved placeholders only against its own explicitly-set `Properties` (plus optionally system properties), so it could not see the Environment's ordered sources. `PropertySourcesPlaceholderConfigurer` is the modern replacement and should always be preferred. ## Spring Boot Boot registers one automatically (`PropertyPlaceholderAutoConfiguration`), so `@Value("${...}")` just works without any manual bean. You typically only declare your own to customize behavior (e.g. `setIgnoreUnresolvablePlaceholders`, a custom placeholder prefix, or supplying extra `Resource` locations). ## The static @Bean requirement If you do declare it yourself: ```java @Configuration public class PropsConfig { @Bean public static PropertySourcesPlaceholderConfigurer placeholders() { return new PropertySourcesPlaceholderConfigurer(); } } ``` The method **must be `static`**. BFPPs are instantiated at the very start of `refresh()`. If the method were an instance method, Spring would have to instantiate `PropsConfig` first to call it — before that config class can be fully processed — producing a warning and potentially leaving the config class un-enhanced. `static` lets Spring invoke the factory method without creating the enclosing configuration bean. ## Common gotchas - **Unresolvable placeholders throw by default.** If `${x}` has no value and no default, context startup fails. Use a `:default` or `setIgnoreUnresolvablePlaceholders(true)`. - **Two configurers fighting.** Declaring your own alongside Boot's can cause one to see placeholders the other already tried to resolve; keep to one, or set `ignoreUnresolvablePlaceholders` so the second pass can finish. - Prefer `@ConfigurationProperties` for grouped, typed config over many scattered `@Value` placeholders.

  • What happens if a ${...} placeholder cannot be resolved and has no default?
    By default the configurer throws and context startup fails fast. You can supply a default with ${key:fallback} or call setIgnoreUnresolvablePlaceholders(true) to leave it unresolved.
  • How is PropertySourcesPlaceholderConfigurer different from the older PropertyPlaceholderConfigurer?
    The newer one resolves against the unified Environment/PropertySources (files, env vars, system props, in precedence order); the legacy one only saw its own locally-set Properties and predates the Environment abstraction.

saying these in an interview costs you the question

  • Saying it resolves placeholders at runtime after beans are built (it does so before, at definition time).
  • Declaring the @Bean non-static in a @Configuration class.
  • Believing it is unrelated to BeanFactoryPostProcessor.
  • Thinking you must always declare it manually in Spring Boot.

context