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.
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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
