What is a BeanFactoryPostProcessor, and at what point in the container lifecycle does it run?
answer
- definitions not instances
- runs before any bean instantiated
- postProcessBeanFactory(ConfigurableListableBeanFactory)
- don't call getBean — skips proxies
- PropertySourcesPlaceholderConfigurer is one
basics
~10 sA BeanFactoryPostProcessor is a Spring hook that runs after the container reads all bean definitions but before it creates any beans. It can change the definitions (metadata), for example resolving ${...} placeholders.
solid answer
~40 sA BeanFactoryPostProcessor (BFPP) is a container extension point that operates on bean *definitions* — the metadata Spring holds about each bean — not on bean instances. After the ApplicationContext loads every bean definition (from @Configuration, XML, component scan, etc.) but before it instantiates any singleton, Spring calls postProcessBeanFactory(ConfigurableListableBeanFactory). Inside, you can read and mutate definitions: change property values, alter scope, add or override attributes. The classic built-in is PropertySourcesPlaceholderConfigurer, which resolves ${...} placeholders against the Environment. Multiple BFPPs run ordered by PriorityOrdered, then Ordered, then the rest. The key rule: don't force bean instantiation from a BFPP, because beans created that early skip BeanPostProcessor treatment (like AOP proxying).
code
java · 16 linesimport org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
public class MakeReportsLazy implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory bf) {
for (String name : bf.getBeanDefinitionNames()) {
BeanDefinition bd = bf.getBeanDefinition(name);
if (bd.getBeanClassName() != null && bd.getBeanClassName().endsWith("Report")) {
bd.setLazyInit(true); // mutate metadata, no instance created
}
}
}
}go deeper
Know it edits definitions before beans exist and that PropertySourcesPlaceholderConfigurer is an example.
Explain the refresh() ordering (definitions loaded -> BFPPs -> BPPs registered -> singletons created) and the getBean anti-pattern.
Contrast BFPP vs BPP crisply, discuss ordering (PriorityOrdered/Ordered) and premature-instantiation consequences.
Discuss when custom BFPPs are justified vs configuration properties/conditions, and framework integrations that rely on definition mutation.
## What it is `BeanFactoryPostProcessor` (BFPP) is a functional interface in `org.springframework.beans.factory.config` with a single method: ```java void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory); ``` It is a **container extension point**. To understand it you need two concepts: - **BeanDefinition** — Spring does not create your beans directly from your classes. It first builds a `BeanDefinition` for each bean: an object holding the metadata (class name, scope, constructor args, property values, lazy flag, init/destroy methods, etc.). Think of it as the recipe, not the cake. - **Bean instance** — the actual object Spring later constructs from that recipe. A BFPP runs on the **recipes**, before any **cake** is baked. ## When it runs (lifecycle position) During `AbstractApplicationContext.refresh()`: 1. Bean definitions are loaded (parsing @Configuration, XML, scanning). 2. **`invokeBeanFactoryPostProcessors()`** — all BFPPs run here. At this moment every definition exists, but no application singleton has been instantiated yet. 3. `registerBeanPostProcessors()` — BeanPostProcessors are registered. 4. `finishBeanFactoryInitialization()` — non-lazy singletons are instantiated. So a BFPP sees the complete set of definitions and can still rewrite them before instantiation. ## What you can do inside - Resolve/override property values (e.g. inject computed values into definitions). - Change a bean's scope or lazy flag. - Add or remove property values / constructor args. - Inspect definitions to enforce conventions. Example: ```java public class ScopeEnforcer implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory bf) { BeanDefinition bd = bf.getBeanDefinition("reportCache"); bd.setScope(BeanDefinition.SCOPE_SINGLETON); } } ``` ## The critical rule: don't instantiate beans A BFPP receives the `BeanFactory`, so it *can* call `getBean(...)`. Doing so is a well-known anti-pattern: it forces a bean to be created during BFPP processing, before `BeanPostProcessor`s (which do AOP proxying, `@Transactional`, `@Async`, etc.) are registered. That bean and anything it drags in get created **un-proxied**, silently breaking transactions/security/AOP. Only touch **definitions**, never instances. ## Ordering When several BFPPs exist, Spring runs them in this order: those implementing `PriorityOrdered`, then `Ordered`, then the remainder. Registry post-processors (see `BeanDefinitionRegistryPostProcessor`) run their registry phase even earlier. ## BFPP vs BeanPostProcessor Easy to confuse: - **BeanFactoryPostProcessor** — operates on **definitions**, runs **once**, before instantiation. - **BeanPostProcessor** — operates on **instances**, runs **per bean**, around initialization (`postProcessBeforeInitialization` / `AfterInitialization`), and is what enables proxying. ## When to use Rarely in application code — most needs are met by `@Value`, `@ConfigurationProperties`, profiles, and conditions. Reach for a BFPP when you must programmatically adjust *existing* definitions (mass property injection, framework/library integration). To *register new* definitions, use the `BeanDefinitionRegistryPostProcessor` sub-interface instead.
- Why is calling getBean() inside a BFPP dangerous?It forces bean instantiation before BeanPostProcessors are registered, so those beans are created without AOP proxies — @Transactional, @Async, security advice, etc. silently stop working for them and anything they pull in.
- What's the difference between a BeanFactoryPostProcessor and a BeanPostProcessor?BFPP operates on bean definitions (metadata), runs once before instantiation. BeanPostProcessor operates on bean instances, runs per-bean around initialization, and is what implements proxying/injection callbacks.
saying these in an interview costs you the question
- Saying a BFPP modifies bean instances (it modifies definitions).
- Claiming it runs after beans are created.
- Thinking calling getBean() in a BFPP is harmless.
- Confusing it with BeanPostProcessor.