Spring BeanPostProcessor beans are a special kind of beans that get created before any other beans and Spring allows you to assign customize callbacks to it. Spring provides the BeanPostProcessor interface, you can implement its methods to provide your own instantiation logic and dependency resolution logic.

NOTE – the following before working with BeanPostProcessor.

  • BeanPostProcessor methods are executed after the Spring IoC finishes instantiating, configuring, and initializing a bean.
  • You can plug in one or more custom BeanPostProcessor implementations.
  • When working with multiple Bean Postprocessors, you should implement the Ordered interface to control the order in which these processors get executed.
  • Remember, the BeanPostProcessor instances are scoped per container.

Example of BeanPostProcessor usage

All you need to do is to implement the interface BeanPostProcessor in your custom class. The interface looks as below, which means you can implement the method that you like and each of them returns bean by default.

public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) 
    throws BeansException {
        return bean;
  }

@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) 
    throws BeansException {
        return bean;
   }
}

All you need to do is implement the interface and implement the callback methods. Below code explains the simple use of the Spring BeanPostProcessor.

@Component
public class TraceBeanPostProcessor implements BeanPostProcessor {

  @Override
  public Object postProcessBeforeInitialization(Object bean, String beanName)
      throws BeansException {
    System.out.println("Inside postProcessBeforeInitialization - " + beanName);
    return bean;
  }

  @Override
  public Object postProcessAfterInitialization(Object bean, String beanName)
      throws BeansException {
    System.out.println("Inside postProcessAfterInitialization - " + beanName);
    return bean;
  }
}
@Component
public class ExampleBean {

  @PostConstruct
  public void initData() {
    System.out.println("Your custom initialization code goes here...");
  }

  @PreDestroy
  public void clearData() {
    System.out.println("Your custom destroy code goes here...");
  }
}
@Configuration
@ComponentScan("core.bean.postprocessor")
public class ExampleConfig {
  //Extra config goes
}
public class TestExampleBean {
  public static void main(String[] args) {

    ConfigurableApplicationContext context
        = new AnnotationConfigApplicationContext(ExampleConfig.class);
    context.getBean(ExampleBean.class);

    //This is important
    context.registerShutdownHook();
  }
}

Output:

Inside postProcessBeforeInitialization exampleConfig
Inside postProcessAfterInitialization exampleConfig
Inside postProcessBeforeInitialization exampleBean
Your custom initialization code goes here...
Inside postProcessAfterInitialization exampleBean
Your custom destroy code goes here...

As you can see in the above output, the bean post-processor methods get invoked twice, once per bean. This is because Spring IoC creates 2 beans here (exampleConfig, and exampleBean).

You can have multiple custom BeanPostProcessor classes in your Spring application, but remember to implement the Ordered interface as well.

A Practical use case of BeanPostProcessor

A practical use case of a bean Post Processor is when you want to wrap the original IoC-created bean in a proxy instance for example when you use @Transactional, Spring-AOP or BeanValidationPostProcessor. I have listed some of the Spring framework classes that make use of the bean post-processor interface.

I hope to have provided enough information on this topic. Please share your thoughts in the comments below. I highly encourage you to check out the article related to the Spring bean lifecycle.