ZetCode

Spring BeanFactoryPostProcessor tutorial

last modified October 18, 2023

Spring BeanFactoryPostProcessor tutorial shows how to use BeanFactoryPostProcessor to modify application context's bean definitions.

Spring is a popular Java application framework for creating enterprise applications.

Spring BeanFactoryPostProcessor

Spring BeanFactoryPostProcessor works on the bean definitions or configuration meta data of the bean before beans are actually created. With BeanFactoryPostProcessor we can modify exiting bean definitions or create our new bean definitions.

Spring provides some built-in implementations of BeanFactoryPostProcessor. For instance, the PropertyPlaceholderConfigurer is a post processor that allows to read properties from external files.

Spring BeanFactoryPostProcessor example

The following application uses BeanFactoryPostProcessor to add a new bean definition.

pom.xml
src
├───main
│   ├───java
│   │   └───com
│   │       └───zetcode
│   │           │   Application.java
│   │           │
│   │           └───config
│   │                   AppConfig.java
│   └───resources
│           logback.xml
└───test
    └───java

This is the project structure.

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.zetcode</groupId>
    <artifactId>beanfactorypostprocessorex</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <spring-version>5.3.23</spring-version>

    </properties>

    <dependencies>

        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.4.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring-version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring-version}</version>
        </dependency> 
        
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>3.1.0</version>
                <configuration>
                    <mainClass>com.zetcode.Application</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

In the pom.xml file, we have basic Spring dependencies spring-core, spring-context, and logging logback-classic dependency.

The exec-maven-plugin is used for executing Spring application from the Maven on the command line.

resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <logger name="org.springframework" level="ERROR"/>
    <logger name="com.zetcode" level="INFO"/>

    <appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
            </Pattern>
        </encoder>
    </appender>

    <root>
        <level value="INFO" />
        <appender-ref ref="consoleAppender" />
    </root>
</configuration>

The logback.xml is a configuration file for the Logback logging library.

com/zetcode/config/AppConfig.java
package com.zetcode.config;

import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

    @Bean
    public static BeanFactoryPostProcessor beanFactoryPostProcessor() {
        return factory -> {

            var registry = (BeanDefinitionRegistry) factory;

            registry.registerBeanDefinition("myBean",
                    BeanDefinitionBuilder.genericBeanDefinition(String.class)
                            .addConstructorArgValue("This is myBean")
                            .getBeanDefinition()
            );
        };
    }
}

AppConfig is the application configuration class. With @Bean we create a BeanFactoryPostProcessor which registers a new simple bean of built-in java.lang.String type. The new bean is registered with registerBeanDefinition.

com/zetcode/Application.java
package com.zetcode;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.GenericXmlApplicationContext;

public class Application {

    private static final Logger logger = LoggerFactory.getLogger(Application.class);

    public static void main(String[] args) {

        var ctx = new GenericXmlApplicationContext("my-beans.xml");

        logger.info("{}", ctx.getBean("myBean"));

        ctx.close();
    }
}

In the Application, we get retrieve the registered bean and print it.

$ mvn -q exec:java
18:53:19.233 INFO  com.zetcode.Application - This is myBean

We run the application.

In this article we have shown how to use BeanFactoryPostProcessor to register a new bean.

Author

My name is Jan Bodnar and I am a passionate programmer with many years of programming experience. I have been writing programming articles since 2007. So far, I have written over 1400 articles and 8 e-books. I have over eight years of experience in teaching programming.

List all Spring tutorials.