Open In App

Spring – BeanPostProcessor

Last Updated : 22 Apr, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

Spring Framework provides BeanPostProcessor Interface. It allows custom modification of new bean instances that are created by Spring Bean Factory. If we want to implement some custom logic such as checking for marker interfaces or wrapping beans with proxies after the Spring container finishes instantiating, configuring, and initializing a bean, we can plug in BeanPostProcessor implementations.

Syntax: 

org.springframework.beans.factory.config
public interface BeanPostProcessor

Methods in BeanPostProcessor Interface

BeanPostProcessor interface consists of two callback methods namely listed as follows: 

  1. postProcessBeforeInitialization() Method
  2. postProcessAfterInitialization() Method

Method 1: postProcessBeforeInitialization():

To apply any custom logic to the given new bean instance before any bean initialization callbacks (like InitializingBean’s afterPropertiesSet or a custom init-method), we can call this BeanPostProcessor method. The bean will already be populated with the property values and the returned bean instance may be a wrapper around the original one.

Syntax:

@Nullable

default Object postProcessBeforeInitialization(Object bean, String beanName) 
throws BeansException

Parameters:

  • The new bean instance
  • The name of the bean

Return Type: Either the original or a wrapped bean instance to use. No subsequent BeanPostProcessors will be invoked, if null. And in case of errors, it throws BeansException.

Method 2: postProcessAfterInitialization():

To apply any custom logic to the given new bean instance after any bean initialization callbacks (like InitializingBean’s afterPropertiesSet or a custom init-method), we can call this BeanPostProcessor method.

The bean will already be populated with the property values and the returned bean instance may be a wrapper around the original one. This callback will be invoked for both the FactoryBean instance and the objects created by the FactoryBean. The post-processor can decide whether to apply to either the FactoryBean or created objects or both through the corresponding bean instance of the FactoryBean checks.

Syntax: 

@Nullable

default Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException

Parameters:

  • The new bean instance
  • The name of the bean

Return Type: Either the original or a wrapped bean instance to use. No subsequent BeanPostProcessors will be invoked, if null. And in case of errors, it throws BeansException.

Registering and Ordering the BeanPostProcessors

We can plug in one or more BeanPostProcessor implementations to include custom logic, in this case, we can control these multiple BeanPostProcessor instances by setting the order property or by implementing the Ordered interface.

An ApplicationContext can autodetect BeanPostProcessor beans in its bean definitions and apply those to any beans that are subsequently created. In case of a plain BeanFactory, we need to register the post-processors programmatically applying them to all beans created through the bean factory.

BeanPostProcessor beans that are autodetected in an ApplicationContext will be ordered according to PriorityOrdered and Ordered interfaces. In contrast, BeanPostProcessor beans that are registered programmatically with a BeanFactory will be applied in the order of registration.

Implementation:

We will create a simple Spring application to get employee details using Eclipse IDE.

Step 1: Create a new Java project ‘Spring_Application’ in Eclipse.

Step 2: Add Spring jar files to the project. We can download the latest jar files from Maven Repository.

Step 3: Now, we need to create the required Java classes and the configuration files under the project. Below will be the final project structure of the application.

Project Structure

Step 4: Create a ‘CustomProcessor.java’ file that implements the BeanPostProcessor interface and implements the two callback methods in it.

Example: Spring BeanPostProcessor

A. File: CustomProcessor.java

Java




// Java Program to Illustrate CustomProcessor Class
 
package com.geeks.beans;
 
// Importing required classes
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
 
// Class
// Implementing BeanPostProcessor interface
public class CustomProcessor implements BeanPostProcessor {
 
    // Method 1
    public Object postProcessBeforeInitialization(
        Object bean, String beanName) throws BeansException
    {
        System.out.println(
            "postProcessBeforeInitialization() is called for EmployeeImpl");
 
        return bean;
    }
 
    // Method 2
    public Object postProcessAfterInitialization(
        Object bean, String beanName) throws BeansException
    {
        System.out.println(
            "postProcessAfterInitialization() is called for EmployeeImpl");
 
        return bean;
    }
}


Step 5: Create an ‘Employee.java’ file to define variables and their getter/setter methods.

B. File: Employee.java

Java




// Java Program to Illustrate Employee Class
 
package com.geeks.beans;
 
// Class
public class Employee {
 
    // Class data members
    private String name;
    private String mail;
 
    // Getter
    public String getName() { return name; }
 
    // Setter
    public void setName(String name) { this.name = name; }
 
    // Getter
    public String getMail() { return mail; }
 
    // Setter
    public void setMail(String mail) { this.mail = mail; }
}


Step 6: Create an ‘EmployeeImpl.java’ file to create a new Employee object. Define Init and Destroy methods of the class.

C. File: EmployeeImpl.java

Java




// Java Program Implementing Employee Class
 
package com.geeks.beans;
 
// Class
public class EmployeeImpl {
 
    // Method 1
    public Employee createEmp()
    {
 
        // Creating Employee class object
        // inside EmployeeImpl class
        Employee e = new Employee();
 
        // Custom setters
        e.setName("Geek");
        e.setMail("test@email.com");
        return e;
    }
 
    // Method 2
    public void initBean()
    {
        System.out.println("EmployeeImpl is Initialized.");
    }
 
    // Method 3
    public void destroyBean()
    {
        System.out.println("EmployeeImpl is Destroyed.");
    }
}


Step 7: Create ‘applicationContext.xml’ Spring configuration file to include bean definitions. Register the BeanPostProcessor in the configuration file.

D. File: applicationContext.xml

XML




<?xml version="1.0" encoding="UTF-8"?>
 
 
    <bean id="beanPostProcessor" class="com.geeks.beans.CustomProcessor" />
    <bean id="impl" class="com.geeks.beans.EmployeeImpl"  init-method="initBean" destroy-method="destroyBean"/>
     
 
</beans>


Step 8: Create an ‘EmployeeTest.java’ file to get the bean and run the application.

E. File: EmployeeTest.java

Java




// Java Program to Illustrate EmployeeTest Class
 
package com.geeks.beans;
 
// Importing required classes
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
// Class
public class EmployeeTest {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Creating object of ApplicationContext,
        // EmployeeImpl, and Employee class inside main()
        // method
        ApplicationContext con
            = new ClassPathXmlApplicationContext(
                "com/geeks/resources/applicationContext.xml");
        EmployeeImpl impl
            = (EmployeeImpl)con.getBean("impl");
        Employee emp = impl.createEmp();
 
        System.out.println("Employee Details");
        System.out.println("Name: " + emp.getName()
                           + ", Email address: "
                           + emp.getMail());
        ((ClassPathXmlApplicationContext)con).close();
    }
}


Step 9: Run the application as a Java application. We will get the below output in the console.

Output

As we can see in the output, postProcessBeforeInitialization() is called before the initialization of the bean and once it is done, postProcessAfterInitialization() method is called and then the rest of the process completed. So, we can include any custom logic using post-processors to the new bean instances either before or after the bean initializations.



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads