A bean post processor allows for custom modification of new bean instances created by spring bean factory. If you want to implement some custom logic after the Spring container finishes instantiating, configuring, and initializing a bean, we can plug in one or more BeanPostProcessor implementations.
In case of multiple BeanPostProcessor instances, we can control the order by setting the order
property or implement Ordered
interface.
Table of contents 1. Spring BeanPostProcessor 2. When BeanPostProcessor methods are called Demo
1. Spring BeanPostProcessor
BeanPostProcessor interface consists of exactly two callback methods i.e. postProcessBeforeInitialization()
and postProcessAfterInitialization()
.
For each bean instance that is created by the container, the post-processor gets a callback from the container both time – before container initialization methods are called as well as after any bean initialization callbacks.
A bean post-processor typically checks for callback interfaces or may wrap a bean with a proxy. Some Spring AOP infrastructure classes (e.g. AbstractAdvisingBeanPostProcessor) are implemented as bean post-processors in order to provide proxy-wrapping logic.
1.1. How to create BeanPostProcessor
To create a bean post processor in spring:
- implement the
BeanPostProcessor
interface. - implement the callback methods.
import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; public class CustomBeanPostProcessor implements BeanPostProcessor { public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("Called postProcessBeforeInitialization() for :" + beanName); return bean; } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("Called postProcessAfterInitialization() for :" + beanName); return bean; } }
1.2. How to register BeanPostProcessor
An ApplicationContext automatically detects any beans that are defined in the configuration metadata which implement the BeanPostProcessor interface. It registers these beans as post-processors so that they can be called later upon bean creation.
Then Spring will pass each bean instance to these two methods before and after calling the initialization callback method where you can process the bean instance the way you like.
<beans> <bean id="customBeanPostProcessor" class="com.howtodoinjava.demo.processors.CustomBeanPostProcessor" /> </beans>
2. When BeanPostProcessor methods are called
Typically spring’s DI container does following things to create a bean, you request for:
- Create the bean instance either by a constructor or by a factory method
- Set the values and bean references to the bean properties
- Call the setter methods defined in the all the aware interfaces
- Pass the bean instance to the
postProcessBeforeInitialization()
method of each bean post processor - Call the initialization callback methods
- Pass the bean instance to the
postProcessAfterInitialization()
method of each bean post processor - The bean is ready to be used
- When the container is shut down, call the destruction callback methods
3. Spring BeanPostProcessor example
To show the example usage, I am using EmployeeDAOImpl
class as follow:
public class EmployeeDAOImpl implements EmployeeDAO { public EmployeeDTO createNewEmployee() { EmployeeDTO e = new EmployeeDTO(); e.setId(1); e.setFirstName("Lokesh"); e.setLastName("Gupta"); return e; } public void initBean() { System.out.println("Init Bean for : EmployeeDAOImpl"); } public void destroyBean() { System.out.println("Init Bean for : EmployeeDAOImpl"); } }
The configuration for this bean and it’s post processor is as follow:
<bean id="customBeanPostProcessor" class="com.howtodoinjava.demo.processors.CustomBeanPostProcessor" /> <bean id="dao" class="com.howtodoinjava.demo.dao.EmployeeDAOImpl" init-method="initBean" destroy-method="destroyBean"/>
Now let’s start the DI container and see the output:
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Called postProcessBeforeInitialization() for : dao Init Bean for : EmployeeDAOImpl Called postProcessAfterInitialization() for : dao
Clearly, BeanPostProcessor methods were called before and after initialization method.
Happy Learning !!