Ebooks

Spring BeanFactoryPostProcessor tutorial

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>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <spring-version>5.1.3.RELEASE</spring-version>

    </properties>

    <dependencies>

        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</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>1.6.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 tutorial, we have shown how to use BeanFactoryPostProcessor to register a new bean.

You might also be interested in these related tutorials: Spring @Qualifier annotation tutorial, Spring Singleton scope bean, Spring c-namespace tutorial, Spring context:property-placeholder tutorial, Spring BeanDefinitionBuilder tutorial, Spring bean reference tutorial, and Java tutorial.