If you want to implement some additional custom logic after the Spring container finishes instantiating, configuring, and initializing a bean, you can plug in one or more BeanPostProcessor implementations.
The BeanPostProcessor interface in the Spring framework defines callback methods that you can implement to perform custom logic on the bean instances. Note that BeanPostProcessors operate on bean instances; the Spring IoC container instantiates a bean instance and then BeanPostProcessors do their work on those created instances. These instances are passed as argument to the callback methods. BeanPostProcessor callback methods are called on each bean created by the Springcontainer.
A bean post-processor typically checks for callback interfaces or may wrap a bean with a proxy.
BeanPostProcessor callback methods
The org.springframework.beans.factory.config.BeanPostProcessor interface has the following two callback methods.
- Object postProcessBeforeInitialization(Object bean, String beanName)- This callback method is called before container initialization methods (such as InitializingBean’s afterPropertiesSet() and any declared init method) are called
- Object postProcessAfterInitialization(Object bean, String beanName) - This method is called after any bean initialization callbacks.
Configuring more than one BeanPostProcessor
You can configure multiple BeanPostProcessor instances. You can also control the order in which these BeanPostProcessors execute by setting the order property. For that the BeanPostProcessor implemenation class must implement the Ordered interface too.
Spring BeanPostProcessor Example
A typical use case for BeanPostProcessor is if you want to have some callback methods for specific type of bean.
Let’s say you have an interface IPayment and two implementation classes CashPayment and CardPayment. For these two beans only (out of all the configured beans) you want some logic to be performed (like doing some validation, checking some value) then you can create a BeanPostProcessor and in it’s callback method postProcessAfterInitialization you can use instanceOf operator to verify if bean is of specific type and then call the method you want.
Inerface IPayment
public interface IPayment extends PaymentCallBack { void executePayment(); }
Interface PaymentCallBack
public interface PaymentCallBack { void processInstance(IPayment bean); }
CashPayment.java
public class CashPayment implements IPayment{ public void executePayment() { System.out.println("Perform Cash Payment "); } @PostConstruct public void annoInitMethod(){ System.out.println("Calling InitMethod for CashPayment"); } @Override public void processInstance(IPayment bean) { System.out.println("processInstance method called with bean " + bean); } }
CardPayment.java
public class CardPayment implements IPayment{ public void executePayment() { System.out.println("Perform Card Payment "); } @PostConstruct public void annoInitMethod(){ System.out.println("Calling InitMethod for CardPayment"); } @Override public void processInstance(IPayment bean) { System.out.println("processInstance method called with bean " + bean); } }
In these classes you can see that Spring bean life cycle initialization method annotated with @PostConstruct is used to see when bean is actually initialized.
BeanPostProcessor Class
A custom bean post processor class in Spring implements BeanPostProcessor interface and provides implementation of callback methods postProcessBeforeInitialization() and postProcessAfterInitialization().
import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.core.Ordered; public class InstantiationBeanPostProcessor implements BeanPostProcessor, Ordered { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("In postProcessBeforeInitialization method"); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("In postProcessAfterInitialization method"); if(bean instanceof IPayment){ ((IPayment) bean).processInstance((IPayment)bean); } return bean; } @Override public int getOrder() { // TODO Auto-generated method stub return 0; } }
XML Configuration
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> <bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" /> <bean id="cashPaymentBean" class="org.netjs.exp.Spring_Example.CashPayment" /> <bean id="cardPaymentBean" class="org.netjs.exp.Spring_Example.CardPayment" /> <bean class="org.netjs.exp.Spring_Example.InstantiationBeanPostProcessor"/> </beans>
Notice how the InstantiationBeanPostProcessor is simply defined that's all is needed to register a BeanPostProcessor. It does not even have a name, and because it is a bean it can be dependency-injected just like any other bean.
You can use the following code to run the preceding code and configuration.public class App { public static void main( String[] args ){ ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("appcontext.xml"); //System.out.println("Loading AnnotationConfig app context"); IPayment cashBean = (IPayment) context.getBean("cashPaymentBean"); IPayment cardBean = (IPayment) context.getBean("cardPaymentBean"); context.close(); } }
Output
In postProcessBeforeInitialization method Calling InitMethod for CashPayment In postProcessAfterInitialization method processInstance method called with bean org.netjs.exp.Spring_Example.CashPayment@1e397ed7 In postProcessBeforeInitialization method Calling InitMethod for CardPayment In postProcessAfterInitialization method processInstance method called with bean org.netjs.exp.Spring_Example.CardPayment@490ab905
That's all for this topic BeanPostProcessor in Spring Framework. If you have any doubt or any suggestions to make please drop a comment. Thanks!
>>>Return to Spring Tutorial Page
Related Topics
You may also like-