Issue
I have a scenario where I want to programmatically inject properties into Spring before any beans are created/initialized:
- The beans (not modifiable) are configured with
ConditionalOnProperty
, so properties need to be set before creation. - Properties need to be configured dynamically and programmatically, not via property file (we call an API and use the result to set the property value).
I see ApplicationContext
has a way to get the current environment's property sources (via ConfigurableEnvironment), but I am not sure how to inject into the Spring lifecycle to configure the ApplicationContext
before beans are initialized.
I'm aware of BeanFactoryPostProcessor as a hook which occurs before bean initialization, but I don't see a way to obtain an instance of ApplicationContext
in it.
How can it be accomplished?
Note: the application itself is Spring Web/MVC, not Spring Boot. The third party library internally uses Spring Boot classes (ConditionalOnProperty
).
Solution
Based on @m-deinum's comment, I was able to get it working with the following:
public class MyPropertyInitializer extends WebMvcConfigurerAdapter implements WebApplicationInitializer, ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
String initializerClasses = servletContext.getInitParameter(ContextLoader.GLOBAL_INITIALIZER_CLASSES_PARAM);
String initClassName = this.getClass().getName();
if (StringUtils.isNotBlank(initializerClasses)) {
initializerClasses += "," + initClassName;
} else {
initializerClasses = initClassName;
}
servletContext.setInitParameter(ContextLoader.GLOBAL_INITIALIZER_CLASSES_PARAM, initializerClasses);
}
@Override
public void initialize(ConfigurableApplicationContext context) {
Properties props = getCustomProperties();
PropertySource<?> propertySource = new PropertiesPropertySource("my-custom-props", props);
context.getEnvironment().getPropertySources().addLast(propertySource);
}
protected Properties getCustomProperties() {
Properties props = new Properties();
// do logic to set desired values
return props;
}
}
Answered By - trebor
Answer Checked By - David Goodson (JavaFixing Volunteer)