What are the Bean Lifecycle Stages?
BPP (BeanPostProcessor) is a Spring mechanism for modifying beans. Key BPPs:
Junior Level
Bean creation stages:
1. Constructor -> object created
2. @Autowired -> dependencies injected
3. @PostConstruct -> initialization
4. Ready to work
5. @PreDestroy -> cleanup on removal
@Service
public class MyService {
private final Repo repo;
// 1. Constructor
public MyService(Repo repo) {
this.repo = repo;
}
// 2. @Autowired already fired (via constructor)
// 3. Initialization
@PostConstruct
public void init() {
System.out.println("Bean is ready!");
}
// 5. Cleanup
@PreDestroy
public void cleanup() {
System.out.println("Bean is being removed");
}
}
Middle Level
This question details the stages from file [[06. What is Bean Lifecycle]]. If that file explains WHY, this one explains HOW exactly (12 steps).
Detailed Order
1. Instantiation (constructor)
2. Populate Properties (@Autowired fields/setters)
3. Aware Interfaces
-> BeanNameAware.setBeanName()
-> BeanFactoryAware.setBeanFactory()
-> ApplicationContextAware.setApplicationContext()
4. BeanPostProcessor.postProcessBeforeInitialization()
5. @PostConstruct
6. InitializingBean.afterPropertiesSet()
7. init-method (@Bean(initMethod="init"))
8. BeanPostProcessor.postProcessAfterInitialization() <- Proxy!
9. READY
10. @PreDestroy
11. DisposableBean.destroy()
12. destroy-method
Singleton vs Prototype
// Singleton:
// -> All stages 1-12
// -> Destroyed when context is closed
// Prototype:
// -> Only stages 1-9
// -> @PreDestroy is NOT called automatically. Spring does not track their destruction. If needed - call cleanup manually or use ConfigurableBeanFactory.registerDestructionCallback().
ContextRefreshedEvent
// When ALL beans are created and initialized:
@EventListener(ContextRefreshedEvent.class)
public void onApplicationReady() {
// All proxies are created, all beans are ready
// Can call @Transactional methods!
}
Senior Level
Instantiation vs Initialization
Instantiation:
-> new Service() via reflection
-> Object exists in Heap
Initialization:
-> Dependency injection
-> @PostConstruct
-> Proxy creation
-> In constructor, dependencies are not yet injected (except Constructor Injection)
BPP Chain
BPP (BeanPostProcessor) is a Spring mechanism for modifying beans. Key BPPs:
- CommonAnnotationBeanPostProcessor - handles @PostConstruct/@PreDestroy
- AutowiredAnnotationBeanPostProcessor - handles @Autowired
- AnnotationAwareAspectJAutoProxyCreator - creates proxies for @Transactional, @Async
Multiple BPPs execute sequentially:
1. CommonAnnotationBeanPostProcessor -> @PostConstruct
2. AutowiredAnnotationBeanPostProcessor -> @Autowired
3. AnnotationAwareAspectJAutoProxyCreator -> Proxy
-> Each can modify or replace the bean
-> Order matters! -> @Order
Early BPP Initialization
// If your BPP depends on MyService:
// -> MyService is created BEFORE other BPPs
// -> MyService may not get a proxy!
// Why: BPPs that create proxies (e.g., AnnotationAwareAspectJAutoProxyCreator for @Transactional) are not yet registered. MyService is created "bare", without a proxy wrapper. Solution: do not inject beans into BPP - use ObjectProvider or ApplicationContext.getBean() with caution.
// Solution: @Lazy or independent BPPs
Production Experience
Real scenario: BPP did not get a proxy
- Custom BPP depended on DataSource
- DataSource was created earlier -> without transactions
- Solution: @Lazy dependency in BPP
- Result: proxy created correctly
Best Practices
- Constructor -> only field assignment
- @PostConstruct -> validation, light initialization
- @PreDestroy -> resource cleanup
- Prototype -> clean up yourself
- ContextRefreshedEvent -> when everything is ready
- BPP dependencies -> @Lazy
Summary for Senior
- 12 stages -> from constructor to destroy
- Proxy created at stage 8 (after @PostConstruct)
- Prototype -> no stages 10-12
- BPP ordering -> important via @Order
- ContextRefreshedEvent -> all beans are ready
- Early initialization -> can break proxy
Interview Cheat Sheet
Must know:
- 12 stages: Instantiation -> Populate Properties -> Aware Interfaces -> BPP Before -> @PostConstruct -> afterPropertiesSet -> init-method -> BPP After (Proxy!) -> Ready -> @PreDestroy -> DisposableBean -> destroy-method
- Aware interfaces:
BeanNameAware,BeanFactoryAware,ApplicationContextAware- bean receives information from container - Proxy created at stage 8 -
BPP.postProcessAfterInitialization(), after@PostConstruct - Singleton goes through all 12 stages, Prototype - only 1-9 (no destroy)
ContextRefreshedEvent- published when ALL beans and proxies are created, can call@Transactionalmethods- Early BPP initialization: if BPP depends on a bean, that bean is created before other BPPs and may not get a proxy
- BPP ordering via
@Order- order matters, each BPP can replace a bean
Common follow-up questions:
- What is the difference between Instantiation and Initialization? Instantiation =
newvia reflection (object exists). Initialization = DI,@PostConstruct, Proxy creation. - What Aware interfaces do you know?
BeanNameAware(bean name),BeanFactoryAware(factory),ApplicationContextAware(context). - Why might a custom BPP not get a proxy? If the bean is created before the BPP that creates proxies - the bean remains “bare”.
- How to manage BPP ordering?
@Orderannotation - lower value = earlier execution.
Red flags (DO NOT say):
- “In constructor, all dependencies are already injected” (except Constructor Injection - dependencies are still NULL)
- “Prototype beans call
@PreDestroy” (no, Spring does not track their destruction) - “BPP order does not matter” (critically important - first BPP can replace the bean for the second)
- “You can pull any dependencies into BPP” (this causes early initialization and breaks proxies)
Related topics:
- [[06. What is Bean Lifecycle]]
- [[08. What is BeanPostProcessor]]
- [[09. What do PostConstruct and PreDestroy methods do]]
- [[04. What is a Bean in Spring]]
- [[10. What is Bean scope]]