Spring Interview Guide: Bean Lifecycle, Creation Process, and BFPP vs BPP Differences
This article explains the complete Spring Bean lifecycle, breaks it down into six major phases and eleven detailed steps, describes how BeanFactory creates beans in four stages, and clearly distinguishes BeanFactoryPostProcessor from BeanPostProcessor with concrete examples and code snippets.
1. Spring Bean lifecycle (6 phases)
Spring creates a bean through the following major stages:
1.1 Bean definition loading
The container reads bean definitions from XML files or annotation‑based configuration such as @Component, @Service, @Repository, and builds a BeanDefinition object.
1.2 Bean instantiation
Using the metadata, Spring instantiates the bean via reflection (e.g., Constructor.newInstance()) or a factory method. All fields are initially set to default values ( null, 0, etc.). For a class annotated with @Service named MyService, Spring calls its no‑arg constructor to create a MyService instance.
1.3 Property population (dependency injection)
Spring injects values into the bean’s fields using @Value, @Autowired, @Resource, etc. If MyService has a field of type MyDao annotated with @Autowired, the container finds the MyDao bean and injects it.
1.4 Initialization
After properties are set, Spring runs initialization callbacks in this order: Aware interfaces, @PostConstruct methods, InitializingBean.afterPropertiesSet(), and finally any custom init‑method. Aware callbacks (e.g., BeanNameAware.setBeanName()) let the bean obtain container information.
1.5 BeanPostProcessor pre‑processing
Before the bean’s own initialization methods, Spring invokes BeanPostProcessor.postProcessBeforeInitialization() on all registered processors. This is where AOP proxies can be created.
1.6 BeanPostProcessor post‑processing
After the bean’s initialization callbacks, Spring calls BeanPostProcessor.postProcessAfterInitialization(). This stage is commonly used for AOP proxy creation (e.g., AnnotationAwareAspectJAutoProxyCreator).
1.7 Usage
The fully initialized bean is stored in the container and can be retrieved by application code.
1.8 Destruction
For singleton beans that define a destroy method, Spring registers the bean so that when the container shuts down it invokes @PreDestroy, DisposableBean.destroy(), or a custom destroy‑method.
2. Detailed 11‑step lifecycle
Instantiation – create raw instance via reflection or FactoryBean.
Populate properties – resolve and inject dependencies.
BeanPostProcessor pre‑processing – call postProcessBeforeInitialization. @PostConstruct callback. InitializingBean.afterPropertiesSet() callback.
Custom init‑method callback.
BeanPostProcessor post‑processing – call postProcessAfterInitialization (AOP proxy creation occurs here).
Bean ready – fully initialized and possibly proxied.
In use – application retrieves and uses the bean. @PreDestroy callback on shutdown.
DisposableBean or custom destroy‑method execution.
3. BeanFactory bean creation (4 steps)
Parse Bean definition : Locate the BeanDefinition containing class name, scope, property values, constructor arguments, etc.
Instantiate bean ( createBeanInstance): If the bean implements FactoryBean, call getObject(); otherwise use the constructor information from the definition to create the instance via reflection.
Dependency injection ( populateBean): Resolve all @Autowired, @Resource, and configuration placeholders, then inject them into the newly created instance.
Initialize bean ( initializeBean): Execute the sequence of Aware callbacks, BeanPostProcessor pre‑processing, @PostConstruct, InitializingBean, custom init‑method, and finally BeanPostProcessor post‑processing.
4. BFPP vs BPP differences
Timing : BFPP runs after bean definitions are loaded but before any bean instance is created; BPP runs after a bean is instantiated, both before and after its own initialization methods.
Target : BFPP operates on BeanDefinition metadata (e.g., modifying property values or scope). BPP operates on the actual bean instance (e.g., adding proxies, extra behavior).
Core method : BFPP implements
postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory). Typical use is PropertyPlaceholderConfigurer to resolve ${} placeholders. BPP provides two methods –
postProcessBeforeInitialization(Object bean, String beanName)and postProcessAfterInitialization(Object bean, String beanName). Typical use is AOP proxy creation.
Scope of execution : BFPP scans the entire BeanFactory and can modify every BeanDefinition. BPP processes each instantiated bean; it can be filtered to specific beans.
Typical examples :
BFPP – custom class that changes a bean’s property value:
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition beanDef = beanFactory.getBeanDefinition("userService");
beanDef.getPropertyValues().add("username", "modifiedName");
}
}BPP – logger or AOP enhancer:
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
if (bean instanceof UserService) {
System.out.println("UserService initialization before");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
// create proxy or add extra behavior
return bean;
}
}In short, BFPP "modifies the blueprint" of beans, while BPP "processes the built product".
Tech Freedom Circle
Crazy Maker Circle (Tech Freedom Architecture Circle): a community of tech enthusiasts, experts, and high‑performance fans. Many top‑level masters, architects, and hobbyists have achieved tech freedom; another wave of go‑getters are hustling hard toward tech freedom.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
