Question 8 · Section 5

What is BeanPostProcessor?

For application code, @Aspect is usually sufficient. Custom BPPs are needed rarely - mainly when writing libraries.

Language versions: English Russian Ukrainian

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

  1. Application code - @Aspect or standard annotations are usually sufficient
  2. Simple logging - use @Aspect + @Around
  3. 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

  1. BPP -> extending Spring for your needs
  2. postProcessAfterInitialization -> proxy creation
  3. @Order -> order management
  4. @Lazy -> avoid early initialization
  5. Do not proxy BPPs -> they are created early
  6. 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) and postProcessAfterInitialization() (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 @Order matters - first can replace a bean, second will get the already replaced one
  • For application code, @Aspect is 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 @Transactional created? In postProcessAfterInitialization() - after @PostConstruct.
  • When to choose BPP vs @Aspect? @Aspect - for application code (logging, monitoring). BPP - for libraries, bean registration, structure changes.
  • What does postProcessBeforeInstantiation return? Can return a proxy instead of creating an object, or null - 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, @Aspect is 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]]