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.
1. Customizing Spring Beans with BeanPostProcessor Interface
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;
}
}
- The
postProcessBeforeInitialization
method is overridden to perform custom logic before a bean is initialized. It prints a message indicating that it’s inside the method, along with the name of the bean being processed. - Similarly, the
postProcessAfterInitialization
method is overridden to perform custom logic after a bean is initialized. It also prints a message indicating that it’s inside the method, along with the name of the bean being processed.
2. Customizing Spring Beans using @PostConstruct and @PreDestroy
The initData
method is annotated with @PostConstruct
, indicating that it should be invoked after the bean has been constructed by the Spring container. This method contains custom initialization code, which will be executed when the bean is initialized.
Similarly, the clearData
method is annotated with @PreDestroy
, indicating that it should be invoked before the bean is destroyed by the Spring container. This method contains custom cleanup or destruction code, which will be executed when the bean is being destroyed.
Both methods provide a way to customize the initialization and destruction lifecycle of the bean, allowing developers to execute specific tasks before or after the bean’s lifecycle events. This can be useful for tasks such as resource allocation, cleanup, or releasing resources associated with the 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.
- The BootstrapContextAwareProcessor in Spring-Tx.
- The ServletContextAwareProcessor in Spring-Web.
- The PersistenceAnnotationBeanPostProcessor in Spring-orm project.
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.