Properties in Spring's BeanFactoryPostProcessor

Last Updated : 23 Jul, 2025

In Spring, the BeanFactoryPostProcessor interface is used to modify the application's bean definitions before the beans are fully initialized. This can be particularly useful when we want to alter or customize the properties of the bean definitions at runtime. Unlike BeanPostProcessor, which works after bean initialization, BeanFactoryPostProcessor operates on the bean definitions themselves.

One common use case of the BeanFactoryPostProcessor is loading an external properties file and injecting those properties into Spring Beans dynamically. This approach allows us to decouple application configuration from the source code and manage configurations more effectively.

BeanFactoryPostProcessor in Spring for External Properties Management

BeanFactoryPostProcessor comes into play during the initialization phase of the Spring IoC (Inversion of Control) container but before any beans are instantiated. This allows us to modify or add bean definitions, and property values, or even replace beans dynamically before they are created.

In Spring, we can load properties files into the context and inject them into beans via PropertySourcesPlaceholderConfigurer, which is often registered as a BeanFactoryPostProcessor. This allows us to define properties in an external file (like application.properties), which can then be injected into the beans.

Flow of Execution

  1. Properties are loaded into the Spring context.
  2. BeanFactoryPostProcessor manipulates the property values.
  3. Beans are created with the modified properties injected.

Implementation of Properties in BeanFactoryPostProcessor

This example project demonstrates how to use BeanFactoryPostProcessor in Spring to load properties from a file and inject them into beans before they are fully initialized.

Step 1: Create a New Spring Boot Project

Create a new Spring Boot project using IntelliJ IDEA. Choose the following options:

  • Name: BeanFactoryPostProcessor-example-demo
  • Language: Java
  • Type: Maven
  • Packaging: Jar

Click on the Next button.

Project Metadata

Step 2: Add the Dependencies

Add the following dependencies into the Spring Boot project:

  • Spring web
  • Spring Boot DevTools
  • Lombok

Click on the Create button.

Add Dependencies

Spring Context Dependency:

Add the following dependency in your pom.xml file:

<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.1.13</version>
</dependency>

Step 3: Configure Application Properties

Add the following properties to your application.properties file:

spring.application.name=BeanFactoryPostProcessor-example-demo
server.port=8080

Step 4: Create the Config.properties File

Create a file named config.properties in the src/main/resources folder. This file will contain the key-value pairs that will be injected into the beans of the Spring Boot Project.

app.name=MySpringApp
app.version=1.0

Step 5: The Bean Class

Create the AppConfig class, which is the Java bean where we will inject the properties from the config.properties file.

AppConfig.java

Java
package com.gfg.beanfactorypostprocessorexampledemo.config;

public class AppConfig {
    private String appName;
    private String appVersion;

    // Getters and Setters
    public String getAppName() {
        return appName;
    }

    public void setAppName(String appName) {
        this.appName = appName;
    }

    public String getAppVersion() {
        return appVersion;
    }

    public void setAppVersion(String appVersion) {
        this.appVersion = appVersion;
    }

    @Override
    public String toString() {
        return "AppConfig [appName=" + appName + ", appVersion=" + appVersion + "]";
    }
}

Explanation:

  • This class represents a simple bean with appName and appVersion fields.
  • These fields will be injected with the values defined in config.properties.

Step 6: Configuration Class with BeanFactoryPostProcessor

Create the Config class to register the BeanFactoryPostProcessor that loads the properties from the config.properties file and injects them into the AppConfig bean of the Spring Application.

Java
package com.gfg.beanfactorypostprocessorexampledemo.config;

import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;

import java.io.IOException;

@Configuration
public class AppConfig {
    private String appName;
    private String appVersion;

    // Getters and Setters

    @Bean
    public static PropertyPlaceholderConfigurer propertyConfigurer() throws IOException {
        PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
        configurer.setLocation(new ClassPathResource("config.properties"));
        return configurer;
    }

    @Bean
    public AppConfig appConfig() {
        AppConfig appConfig = new AppConfig();
        appConfig.setAppName(appName);
        appConfig.setAppVersion(appVersion);
        return appConfig;
    }
}

Explanation:

  • This class is annotated with @Configuration and contains the Spring configuration.
  • The propertyConfigurer() method defines the BeanFactoryPostProcessor (specifically PropertyPlaceholderConfigurer), which loads the properties file (config.properties) and makes those properties available for injection.
  • The appConfig() method defines the AppConfig bean that will have its properties injected.

Step 7: Main Class

Create the main class that runs the Spring application and prints the injected values from the properties file..

Java
package com.gfg.beanfactorypostprocessorexampledemo;

import com.gfg.beanfactorypostprocessorexampledemo.config.AppConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

@SpringBootApplication
public class BeanFactoryPostProcessorExampleDemoApplication {

    public static void main(String[] args) {
        // Create the Spring application context
        ApplicationContext context = new AnnotationConfigApplicationContext("com.gfg.beanfactorypostprocessorexampledemo.config");

        // Get the AppConfig bean
        AppConfig appConfig = context.getBean(AppConfig.class);

        // Print the values injected from the config.properties file
        System.out.println(appConfig);
    }
}

Explanation:

  • This class creates the application context (AnnotationConfigApplicationContext) and retrieves the AppConfig bean.
  • Finally, it prints the values of the properties (appName and appVersion), which have been injected from the config.properties file.

pom.xml File:

Here’s a sample pom.xml for our Spring Boot application:

XML
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.gfg</groupId>
    <artifactId>BeanFactoryPostProcessor-example-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>BeanFactoryPostProcessor-example-demo</name>
    <description>BeanFactoryPostProcessor-example-demo</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.1.13</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

Step 8: Run the Application

To run the application, execute the following command:

mvn spring-boot:run

You should see the output similar to below:

Output

This confirms that the properties were successfully loaded from the config.properties file and injected into the AppConfig bean.

Conclusion

In this article, we explored how to use BeanFactoryPostProcessor in Spring to load properties from an external file (config.properties) and inject them into a bean (AppConfig) dynamically. This approach allows for flexible configuration management, separating application logic from configuration settings. By utilizing BeanFactoryPostProcessor, you can customize and manipulate your Spring application's properties effectively, enhancing maintainability and scalability.

Comment

Explore