Spring Core - BeanPostProcessor - Example

In Spring framework, the BeanPostProcessor is an interface that contains two callback methods: postProcessBeforeInitialization and postProcessAfterInitialization

BeanPostProcessor 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 by plugging in one or more BeanPostProcessor implementations.

As we mentioned earlier, BeanPostProcessor consists of two callback methods:

1. postProcessBeforeInitializationWe can call this method to apply any custom logic (such as InitializingBean's afterPropertiesSet or a custom init-method) to the given new bean instance before any bean initialization callbacks.

2. postProcessAfterInitializationWe can call this method to apply any custom logic (such as InitializingBean's afterPropertiesSet or a custom init-method) to the given new bean instance after any bean initialization callbacks.

@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {

@Override
public Object postProcessBeforeInitialization(
Object bean, String beanName) throws BeansException {

// Your logic

return bean;
}

@Override
public Object postProcessAfterInitialization(
Object bean, String beanName) throws BeansException {

// Your logic

return bean;
}
}


As long as the BeanPostProcessor implements the Ordered or PriorityOrdered interface, you can configure several BeanPostProcessor interfaces and regulate the sequence in which these interfaces run by modifying the order property.

@Component
public class CustomBeanPostProcessor implements BeanPostProcessor, Ordered {

@Override
public Object postProcessBeforeInitialization(
Object bean, String beanName) throws BeansException {

// Your logic

return bean;
}

@Override
public Object postProcessAfterInitialization(
Object bean, String beanName) throws BeansException {

// Your logic

return bean;
}

@Override
public int getOrder() {
return HIGHEST_PRECEDENCE;
}
}


Complete example

We are creating a simple maven project. You could clone the code from our GitHub repo.

Final Project Directory


Complete pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.knf.dev.demo</groupId>
<artifactId>spring-beanpostprocessor-example</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.1.0</version>
</dependency>
</dependencies>
</project>

BeanPostProcessor Implementation

Create a CustomBeanPostProcessor class that implements the BeanPostProcessor interface and implements the two callback methods in it.

package com.knf.dev.demo;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {

@Override
public Object postProcessBeforeInitialization(
Object bean, String beanName) throws BeansException {
System.out.println(
"postProcessBeforeInitialization() is called for " + beanName);

return bean;
}

@Override
public Object postProcessAfterInitialization(
Object bean, String beanName) throws BeansException {
System.out.println(
"postProcessAfterInitialization() is called for " + beanName);

return bean;
}
}
As long as the BeanPostProcessor implements the Ordered or PriorityOrdered interface, you can configure several BeanPostProcessor interfaces and regulate the sequence in which these interfaces run by modifying the order property.

Create UserService

Here we are customizing Spring Beans using init Method and destroy Method.initMethod is called after bean initialization and the destroyMethod is called before bean destruction by container.

package com.knf.dev.demo;

import org.springframework.stereotype.Component;

@Component
public class UserService {

public void init() {
System.out.println("Perform initialization task.");
}

public void destroy() {
System.out.println("Perform destructive task or release resources.");
}

public void printMessage() {
System.out.println("Hello");
}
}

 

Create Config.java

package com.knf.dev.demo;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.knf.dev.demo")
public class Config {

@Bean(initMethod = "init", destroyMethod = "destroy")
public UserService userService() {
return new UserService();
}

}


Create Application.java

Create an Application class to get the bean and run the application.

package com.knf.dev.demo;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;

public class Application {

public static void main(String[] args) {

AbstractApplicationContext context =
new AnnotationConfigApplicationContext(Config.class);
UserService myComponent = context.getBean(UserService.class);
myComponent.printMessage();

context.close();
}
}

The AbstractApplicationContext.close() method will close the application context, destroying all cached singleton beans and perform finalization like calling the destroy methods.


Console Output

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 (config, and userService).


Source Code 

Popular posts from this blog

Learn Java 8 streams with an example - print odd/even numbers from Array and List

Java Stream API - How to convert List of objects to another List of objects using Java streams?

Registration and Login with Spring Boot + Spring Security + Thymeleaf

Java, Spring Boot Mini Project - Library Management System - Download

ReactJS, Spring Boot JWT Authentication Example

Top 5 Java ORM tools - 2024

Java - Blowfish Encryption and decryption Example

Spring boot video streaming example-HTML5

Google Cloud Storage + Spring Boot - File Upload, Download, and Delete