08 - Spring BeanPost Processors

8.1 Overview of Spring BeanPost Processors

Quite often you will find yourself in a situation where you would need to perform some processing pre and post instantiationof the bean by Spring framework. Spring has provided BeanPostProcessor interface which defines a callback methods to achieve this functionality.

Classes that implements BeanPostProcessor interface needs to be defined in an ApplicationContext(spring bean configuration file) and will be applied on all the beans defined in an application context.

In case there are multiple BeanPostProcessor implementations configured in beans configuration files and they are dependent on each other ( processed object of one implementation can be an input to another) then the order in which post processors is important .To control the order in which post processor will be executed, bean post processor classes need to implement Ordered interface and implement its getOrder methodto define the order.

BeanPostProcessor interface provides us two extension points –

  1. To perform custom processing after the object is instantiated by Spring Container but before
  2. after the initialization.

The BeanPostProcessors operate on bean (or object) instances. This means Spring IoC container instantiates a bean instance and then BeanPostProcessor interfaces do their work.

Note: Notice that the init and destroy methods related to bean are different from bean post processors. BeanPostProcessors are common for all beans and gets executed before custom init methods .

8.2 BeanPostProcessor Interface

BeanPostProcessor interface is defined under org.springframework.beans.factory.config.BeanPostProcessor package and has two callback methods

a) postProcessBeforeInitialization– This method gets called after the object is instantiated but before initialization. Signature of this method is

public Object postProcessBeforeInitialization(Object bean, String beanName)
throwsBeansException

b) postProcessAfterInitialization - This method gets called after the object is initialized . Signature of this method is

public Object postProcessAfterInitialization(Object bean, String beanName)
throwsBeansException

Note: Both the methods returns Object type which means even a complete different object can be returned.

8.3 Example- Write an example to demonstrate the Spring bean post processors

Solution:

a) Create a bean “MessageBean” which will have custom init methods

publicclassMessageBean {
       private String message;
       publicMessageBean()
       {
              System.out.println("Constructor of  bean is called !! ");
       }
       publicvoidinit() throws Exception {
              System.out.println("custom custom init method of  bean is called !! ");
       }
       publicvoid destroy() throws Exception {
               System.out.println(" custom destroy  method of  bean is called !! ");
       }
       public String getMessage() {
              return message;
       }
       publicvoidsetMessage(String message) {
              this.message = message;
       }
}

b) Create a bean post processor “MessageBeanPostProcessor” which will print messages

importorg.springframework.beans.BeansException;
importorg.springframework.beans.factory.config.BeanPostProcessor;
public class MessageBeanPostProcessor implements BeanPostProcessor{
   @Override
   public Object postProcessAfterInitialization(Object bean, String beanName)
       throwsBeansException {
       System.out.println("Post Process After Initialization method is called : Bean Name " + beanName);
       if(bean instanceofMessageBean)
       {
          MessageBeanmessageBean = (MessageBean)bean;
          System.out.println("Value of Message is : " + messageBean.getMessage());
       }
       return bean;
       }
   @Override
   public Object postProcessBeforeInitialization(Object bean, String beanName)
       throwsBeansException {
       System.out.println("Post Process Before Initialization method is called : Bean Name " + beanName);
       if(bean instanceofMessageBean)
       {
           MessageBeanmessageBean = (MessageBean)bean;
           System.out.println("Value of Message is : " + messageBean.getMessage());
           messageBean.setMessage("Updated Test Message");
       }
       return bean;  }
}

c) Define  a entry of MessageBeanPostProcessor and MessageBean in beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

      <bean id="messageBean" init-method="init"       destroy-method="destroy" class="MessageBean" >
              <property name="message" value="Test Message"></property>
      </bean>
      <bean id="messageBeanPostProcessor"      class="MessageBeanPostProcessor" />
</beans>

d) Create TestMessageBean program to test the bean post processors

importorg.springframework.context.ApplicationContext;
importorg.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestMessageBean {
    public static void main(String[] args) {
        ApplicationContext context = 
                newClassPathXmlApplicationContext("beans.xml");
        MessageBean bean = (MessageBean)context.getBean("messageBean");
        ((AbstractApplicationContext) context).registerShutdownHook();
        }
}

e) Run the program

As you can see , we update the message in postProcessBeforeInitialization which is being reflected in postProcessPostInitialization method

Like us on Facebook