What is BeanPostProcessor?
For application code, @Aspect is usually sufficient. Custom BPPs are needed rarely - mainly when writing libraries.
Junior Level
BeanPostProcessor (BPP) is a Spring mechanism for modifying beans after their creation.
Why: BPP is needed when you want to add behavior to beans without changing their code. For example: create a proxy for transactions (@Transactional), add logging (@Aspect), wrap in cache (@Cacheable). ALL Spring annotations that add behavior work through BPP.
Simple analogy: A factory produces toys, and BPP is the quality control department that can add a sticker, packaging, or even replace the toy.
@Component
public class MyBPP implements BeanPostProcessor {
// BEFORE initialization (@PostConstruct)
public Object postProcessBeforeInitialization(Object bean, String name) {
return bean; // Can modify or replace
}
// AFTER initialization
public Object postProcessAfterInitialization(Object bean, String name) {
return bean; // This is where proxies are created!
}
}
Middle Level
What BPP Does
1. Bean constructor
2. Dependency injection
3. BPP.postProcessBeforeInitialization()
4. @PostConstruct
5. BPP.postProcessAfterInitialization() <- Proxy created here!
6. Bean is ready
Proxy Creation
@Override
public Object postProcessAfterInitialization(Object bean, String name) {
if (bean.getClass().isAnnotationPresent(Transactional.class)) {
// Create proxy with transactions
return proxyFactory.createProxy(bean);
}
return bean; // Regular bean without changes
}
Custom Annotations
// Your own annotation
@Target(METHOD)
@Retention(RUNTIME)
public @interface LogExecution { }
// BPP for logging
@Component
public class LoggingBPP implements BeanPostProcessor {
public Object postProcessAfterInitialization(Object bean, String name) {
// Create proxy for logging methods with @LogExecution
return LoggingProxy.create(bean);
}
}
BPP vs BeanFactoryPostProcessor
BeanFactoryPostProcessor:
-> Works with BeanDefinition (before bean creation)
-> Changes recipes
BeanPostProcessor:
-> Works with bean instances
-> Changes objects
Senior Level
BPP vs @Aspect: What to Choose
BPP works at the bean creation level (once at startup). Use for: bean registration, structure changes, proxy wrapping.
@Aspect works at the method call level (on every call). Use for: logging, transactions, caching, monitoring.
For application code, @Aspect is usually sufficient. Custom BPPs are needed rarely - mainly when writing libraries.
When NOT to Use a Custom BPP
- Application code - @Aspect or standard annotations are usually sufficient
- Simple logging - use @Aspect + @Around
- Modifying a single bean - better to edit the bean itself or use @Bean method
InstantiationAwareBeanPostProcessor
An extended version of BPP that allows intervention EVEN BEFORE object creation (postProcessBeforeInstantiation) and IMMEDIATELY AFTER constructor but BEFORE dependency injection (postProcessAfterInstantiation).
// Extended BPP:
public class MyBPP implements InstantiationAwareBeanPostProcessor {
// BEFORE object creation
public Object postProcessBeforeInstantiation(Class<?> beanClass, String name) {
// Can return a proxy instead of creating a real object
return null; // null = create as usual
}
// AFTER constructor, BEFORE dependency injection
public boolean postProcessAfterInstantiation(Object bean, String name) {
return true; // true = continue injection
}
}
Early BPP Initialization
If BPP depends on MyService:
-> MyService is created BEFORE all BPPs are registered
-> MyService may not get a proxy!
Solution:
-> @Lazy dependencies in BPP
-> Or independent BPPs
BPP Ordering
@Order(1)
public class FirstBPP implements BeanPostProcessor { }
@Order(2)
public class SecondBPP implements BeanPostProcessor { }
-> Order matters!
-> First BPP can replace the bean -> second will get the already replaced one
Production Experience
Real scenario: custom @Cache annotation
// Custom @CustomCache annotation
@CustomCache(ttl = 3600)
public Data getData() { }
// BPP creates a proxy with caching
// -> Call -> check cache -> if not -> method -> save to cache
Best Practices
- BPP -> extending Spring for your needs
- postProcessAfterInitialization -> proxy creation
- @Order -> order management
- @Lazy -> avoid early initialization
- Do not proxy BPPs -> they are created early
- InstantiationAwareBPP -> control before creation
Summary for Senior
- BPP -> modifying beans after creation
- Proxy created in postProcessAfterInitialization
- InstantiationAwareBPP -> control BEFORE creation
- Order -> matters with multiple BPPs
- Early initialization -> can break proxies
- BFPP vs BPP -> metadata vs instances
Interview Cheat Sheet
Must know:
- BPP (BeanPostProcessor) - Spring mechanism for modifying/wrapping beans after creation
- Two methods:
postProcessBeforeInitialization()(before@PostConstruct) andpostProcessAfterInitialization()(after, proxies are created here!) - ALL Spring annotations that add behavior work through BPP:
@Transactional,@Async,@Cacheable,@Aspect - BPP vs BFPP: BPP works with bean instances, BFPP - with BeanDefinition (before bean creation)
InstantiationAwareBeanPostProcessor- extended version: control BEFORE creation and AFTER constructor but BEFORE DI- BPP ordering via
@Ordermatters - first can replace a bean, second will get the already replaced one - For application code,
@Aspectis usually sufficient; custom BPPs are rarely needed (mainly for libraries) - Early initialization: if BPP depends on a bean, that bean may not get a proxy - use
@Lazy
Common follow-up questions:
- Where is the proxy for
@Transactionalcreated? InpostProcessAfterInitialization()- after@PostConstruct. - When to choose BPP vs @Aspect?
@Aspect- for application code (logging, monitoring). BPP - for libraries, bean registration, structure changes. - What does
postProcessBeforeInstantiationreturn? Can return a proxy instead of creating an object, ornull- then Spring creates as usual. - Why can’t BPPs be proxied? They are created early in the container lifecycle - may not get their own proxy wrapper.
Red flags (DO NOT say):
- “BPP is the main tool for application code” (for applications,
@Aspectis usually enough, BPP is for libraries) - “BPP and BFPP are the same thing” (BFPP changes BeanDefinition before creation, BPP changes instances after)
- “BPP order does not matter” (critically important - first BPP can replace the bean)
- “You can freely inject beans into BPP” (causes early initialization, breaks proxies)
Related topics:
- [[06. What is Bean Lifecycle]]
- [[07. What are the Bean Lifecycle stages]]
- [[09. What do PostConstruct and PreDestroy methods do]]
- [[04. What is a Bean in Spring]]
- [[01. What is Dependency Injection]]