Beyond @Value: Two painless ways to inject properties early in Spring Boot

This article explains why @Value, @ConfigurationProperties, and Environment cannot be used directly in BeanFactoryPostProcessor, and demonstrates two practical techniques—using Environment#getProperty and Binder with @ConfigurationProperties—to inject configuration properties without pain in early Spring Boot initialization.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Beyond @Value: Two painless ways to inject properties early in Spring Boot

In Spring, @Value, Environment, and @ConfigurationProperties inject configuration properties via a BeanPostProcessor, which runs after BeanFactoryPostProcessor processing. Therefore these annotations cannot be used inside a BeanFactoryPostProcessor.

Injecting properties with Environment

Use the Environment abstraction to read properties early in the container lifecycle.

Method 1 – Direct Environment#getProperty

@Bean
public static BeanFactoryPostProcessor beanFactoryPostProcessor(Environment environment) {
    return beanFactory -> {
        String title = environment.getProperty("pack.app.title", String.class);
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
        registry.registerBeanDefinition("packTitle",
            BeanDefinitionBuilder.genericBeanDefinition(String.class)
                .addConstructorArgValue(title)
                .getBeanDefinition());
    };
}

This approach reads a single property value directly. It is simple but becomes verbose when many properties are required.

Method 2 – Binder with @ConfigurationProperties

@Bean
public BeanFactoryPostProcessor packBeanFactoryPostProcessor(Environment environment) {
    return beanFactory -> {
        BindResult<AKFProperties> result = Binder.get(environment)
            .bind("pack.app", AKFProperties.class);
        AKFProperties properties = result.get();
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
        registry.registerBeanDefinition("packTitle",
            BeanDefinitionBuilder.genericBeanDefinition(App.class)
                .addConstructorArgValue(properties.getTitle())
                .addConstructorArgValue(properties.getVersion())
                .getBeanDefinition());
    };
}

@ConfigurationProperties(prefix = "pack.app")
public static class AKFProperties {
    private String title;
    private String version;
    // getters and setters
}

The Binder loads the entire property group into a POJO, making management of multiple settings easier.

Component‑based registration

Declare a class that implements BeanFactoryPostProcessor and EnvironmentAware so the Environment can be injected.

@Component
public class PackAppBeanFactoryPostProcessor implements BeanFactoryPostProcessor, EnvironmentAware {
    private Environment environment;

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        String title = environment.getProperty("pack.app.title", String.class);
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
        registry.registerBeanDefinition("packTitle",
            BeanDefinitionBuilder.genericBeanDefinition(App.class)
                .addConstructorArgValue(title)
                .getBeanDefinition());
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }
}

Constructor injection or @Resource cannot be used for Environment in a BeanFactoryPostProcessor because the bean instance is created before those mechanisms are active.

Key warnings

Do not use @Value inside a BeanFactoryPostProcessor – the corresponding BeanPostProcessor has not run yet.

Avoid @Resource or constructor injection for Environment in this context.

These approaches enable early‑stage property injection for Spring Boot 3.5.0 applications.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Spring BootconfigurationpropertiesbinderenvironmentBeanFactoryPostProcessorproperty-injection
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.