skip to content

Scopes & Bean Lifecycle

Bean scopes from singleton to request, the callbacks Spring fires as a bean is created and destroyed, the post-processors that can rewrite beans and definitions, and how circular references get resolved. Interviewers use this area to find out how deep your model of the container really goes.

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

explore

questions

page 1 of 2

What is a BeanFactoryPostProcessor, and at what point in the container lifecycle does it run?

level: juniorimportance: must knowfreq 55%

answer

  1. definitions not instances
  2. runs before any bean instantiated
  3. postProcessBeanFactory(ConfigurableListableBeanFactory)
  4. don't call getBean — skips proxies
  5. PropertySourcesPlaceholderConfigurer is one

basics

~10 s

A 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 s

A 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 lines
java
import 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

for a junior

Know it edits definitions before beans exist and that PropertySourcesPlaceholderConfigurer is an example.

for a middle

Explain the refresh() ordering (definitions loaded -> BFPPs -> BPPs registered -> singletons created) and the getBean anti-pattern.

for a senior

Contrast BFPP vs BPP crisply, discuss ordering (PriorityOrdered/Ordered) and premature-instantiation consequences.

for a principal

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.

context

open as a page

What is a BeanPostProcessor in Spring and when do its methods run?

level: juniorimportance: must knowfreq 72%

basics

~10 s

A BeanPostProcessor is a Spring extension point with two callbacks that run on every bean after it is constructed and dependencies are injected — one just before the bean's init method, one just after.

open as a page

What is the difference between the default singleton scope and prototype scope in Spring?

level: juniorimportance: must knowfreq 85%

basics

~10 s

A singleton bean is created once per Spring container and shared everywhere. A prototype bean gives a brand-new instance every time it is requested or injected. Singleton is the default.

open as a page

What is a circular dependency between Spring beans, and how does Spring's handling differ between setter/field injection and constructor injection?

level: juniorimportance: must knowfreq 70%

basics

~20 s

A circular dependency is when bean A needs B and B needs A. Spring can resolve this for setter/field injection (it injects a half-built A into B), but constructor injection fails because neither bean can be built first.

open as a page

What is the @DependsOn annotation in Spring and what problem does it solve?

level: juniorimportance: must knowfreq 55%

basics

~10 s

@DependsOn forces named beans to be created (fully initialized) before the annotated bean. It expresses an initialization-order dependency between beans that have no direct injection relationship.

open as a page

What are the ways to run custom code when a Spring bean is initialized or destroyed?

level: juniorimportance: must knowfreq 70%

basics

~10 s

Three ways: annotate a method with @PostConstruct (init) or @PreDestroy (destroy); implement InitializingBean/DisposableBean interfaces; or set initMethod/destroyMethod on @Bean. Spring calls these automatically around the bean's life.

open as a page

What are the Spring Lifecycle and SmartLifecycle interfaces, and what do start(), stop() and isRunning() do?

level: juniorimportance: must knowfreq 55%

basics

~10 s

Lifecycle lets a bean receive start()/stop() callbacks tied to the container. isRunning() reports its state. SmartLifecycle extends it, adding auto-start on context refresh and a phase, so you rarely call start() yourself.

open as a page

What are Spring's web scopes (request, session, application, websocket), and how do they differ from singleton and prototype?

level: juniorimportance: must knowfreq 70%

basics

~20 s

Web scopes tie a bean's lifetime to a web context: request (one HTTP request), session (one user session), application (the ServletContext), and websocket (a WebSocket session). Singleton lives for the whole container; prototype creates a new instance per lookup.

open as a page

You inject a prototype bean into a singleton with plain @Autowired. Why do you keep getting the same prototype instance, and how do you fix it?

level: middleimportance: must knowfreq 80%

basics

~20 s

Injection happens once, when the singleton is created, so the prototype is resolved a single time and reused forever. To get a fresh instance per use, ask the container each time — via ObjectProvider, @Lookup, JSR-330 Provider, or a scoped proxy.

open as a page

Why do constructor-injection circular dependencies fail while field/setter cycles can be resolved? Explain in terms of Spring's bean creation phases.

level: middleimportance: must knowfreq 65%

basics

~20 s

Spring builds a bean in two steps: construct it, then inject its dependencies. Constructor injection needs the dependency at step one, before any object exists to expose, so the cycle can't be broken. Field/setter injection happens at step two, after a half-built object exists to hand out.

open as a page

If a bean uses @PostConstruct, implements InitializingBean, and also declares an @Bean initMethod, in what order do the init callbacks run?

level: middleimportance: must knowfreq 65%

basics

~10 s

First @PostConstruct, then InitializingBean.afterPropertiesSet(), then the @Bean initMethod. Destruction mirrors it: @PreDestroy, then DisposableBean.destroy(), then the @Bean destroyMethod.

open as a page

How does getPhase() control the order of startup and shutdown across SmartLifecycle beans?

level: middleimportance: must knowfreq 50%

basics

~20 s

getPhase() returns an int. On startup, lower phases start first; on shutdown the order reverses, so higher phases stop first and lower phases stop last. This lets low-level infrastructure start early and shut down last.

open as a page

Why do you need a scoped proxy (proxyMode = TARGET_CLASS) when injecting a request- or session-scoped bean into a singleton?

level: middleimportance: must knowfreq 80%

basics

~20 s

A singleton is created once, so if you inject a short-lived bean directly it captures one stale instance forever. A scoped proxy injects a proxy that, on each method call, looks up the correct current-request/session instance.

open as a page

Why is implementing Aware interfaces generally discouraged, and when is using one still justified?

level: seniorimportance: must knowfreq 55%

basics

~20 s

Aware interfaces couple your class to Spring types, hurting testability and portability. Prefer plain dependency injection — inject Environment, ApplicationEventPublisher, or ResourceLoader directly. Use Aware only for infrastructure needs like a bean knowing its own name or doing programmatic getBean lookups.

open as a page

What are Spring's *Aware interfaces, and what does BeanNameAware do?

level: juniorimportance: should knowfreq 45%

basics

~10 s

Aware interfaces are callback interfaces a bean implements to receive a piece of Spring container infrastructure. Spring calls a setter during startup. BeanNameAware.setBeanName gives the bean the id it is registered under.

open as a page

How do you declare a bean as a prototype, and where is @Scope placed on component-scanned vs @Bean-method beans?

level: juniorimportance: should knowfreq 55%

basics

~10 s

Add @Scope("prototype") — or @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE). Put it on the @Component class for scanned beans, or on the @Bean method in a @Configuration class for factory-defined beans.

open as a page

Name the main *Aware interfaces for injecting container infrastructure and what each hands the bean.

level: middleimportance: should knowfreq 50%

basics

~10 s

BeanNameAware gives the bean name, BeanFactoryAware gives the BeanFactory, ApplicationContextAware gives the ApplicationContext, EnvironmentAware gives the Environment, and ResourceLoaderAware gives a ResourceLoader for loading files/URLs.

open as a page

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

level: middleimportance: should knowfreq 45%

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.

open as a page

What is the difference between postProcessBeforeInitialization and postProcessAfterInitialization, and why do proxies get created in the 'after' method?

level: middleimportance: should knowfreq 58%

basics

~10 s

'Before' runs just ahead of a bean's init callbacks; 'after' runs just after them. Proxies are created in 'after' so the wrapped object already had its @PostConstruct and afterPropertiesSet run on the real target.

open as a page

What is the allowCircularReferences / spring.main.allow-circular-references setting, what changed in Spring Boot 2.6, and what are its limits?

level: middleimportance: should knowfreq 50%

basics

~10 s

It's a flag controlling whether Spring resolves setter/field circular dependencies. Since Spring Boot 2.6 it defaults to false, so cycles fail fast at startup. Set spring.main.allow-circular-references=true to re-enable. It never fixes constructor cycles.

open as a page

How does @DependsOn affect bean destruction order at container shutdown?

level: middleimportance: should knowfreq 40%

basics

~10 s

Destruction is the reverse of creation. If A @DependsOn B, then B is created before A, so at shutdown A is destroyed before B. The depended-on bean is torn down last.

open as a page

You inject a @RequestScope bean into a @RestController. Is a scoped proxy required, and what determines the answer?

level: middleimportance: should knowfreq 40%

basics

~20 s

It depends on the controller's scope. A @RestController is a singleton by default, so injecting a request-scoped bean into it needs a scoped proxy. Only if the controller were itself request-scoped could you inject without a proxy.

open as a page

How does ApplicationContextAwareProcessor work, and why do ApplicationContextAware-family callbacks fire at a different time than BeanNameAware?

level: seniorimportance: should knowfreq 35%

basics

~10 s

ApplicationContextAwareProcessor is a BeanPostProcessor the ApplicationContext registers. In its postProcessBeforeInitialization it calls the context-level Aware setters. BeanNameAware and BeanFactoryAware run earlier, directly in the bean factory's invokeAwareMethods.

open as a page

How does BeanDefinitionRegistryPostProcessor differ from BeanFactoryPostProcessor, and in what order do their methods run?

level: seniorimportance: should knowfreq 38%

basics

~10 s

BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor and adds a method to register brand-new bean definitions. Its registry method runs first (for all such processors), then all the postProcessBeanFactory methods run.

open as a page

Why must BeanFactoryPostProcessor (and BeanPostProcessor) @Bean methods be declared static inside a @Configuration class?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Because these post-processors are created very early, before the @Configuration class is processed. A static @Bean method can be called without instantiating the config class, so the container avoids creating it prematurely (which would trigger warnings and skip enhancement).

open as a page

What does InstantiationAwareBeanPostProcessor add over a plain BeanPostProcessor?

level: seniorimportance: should knowfreq 40%

basics

~20 s

It adds hooks that fire around instantiation itself — before the constructor runs and after, during property population — whereas a plain BeanPostProcessor only wraps the later initialization phase. It can even short-circuit creation by returning a substitute object.

open as a page

Explain the lifecycle-callback and resource-cleanup differences between singleton and prototype beans, and how you'd reliably clean up a prototype that holds a resource.

level: seniorimportance: should knowfreq 55%

basics

~20 s

For singletons Spring runs both init (@PostConstruct) and destroy (@PreDestroy) callbacks. For prototypes it runs init but never destroy — the container stops tracking them. Clean up prototypes yourself, or via a custom destroy hook you invoke.

open as a page

How does @Lazy break a circular dependency, and why does it work even for constructor injection where the three-level cache cannot?

level: seniorimportance: should knowfreq 55%

basics

~20 s

@Lazy on an injection point makes Spring inject a lazy proxy instead of the real bean. The proxy is created immediately with no dependency on the target, so construction succeeds; the real bean is looked up only when a method is first called, by which time both beans exist.

open as a page

Explain Spring's three-level singleton cache and how it resolves a setter/field circular dependency, including what each level holds.

level: seniorimportance: should knowfreq 55%

basics

~20 s

DefaultSingletonBeanRegistry keeps three maps: singletonObjects (fully built beans), earlySingletonObjects (raw early references), and singletonFactories (ObjectFactories that produce an early reference on demand). During a cycle, a dependent gets the early reference via the factory, which is promoted to the early-objects map, breaking the loop.

open as a page

What are the key edge cases and gotchas of @DependsOn: circular depends-on, interaction with @Lazy, and exactly what 'initialized before' guarantees?

level: seniorimportance: should knowfreq 30%

basics

~10 s

A depends-on cycle fails startup with a BeanCreationException. @DependsOn forces the target to be created even if it's @Lazy, defeating laziness. 'Initialized before' means fully created including @PostConstruct/afterPropertiesSet, not just constructed.

open as a page

showing 1–30 of 45