I have a maven multimodule SpringBoot web application. I have a submodule, called config-module which has a configuration class:
@Configuration
public class PropertiesConfig {
@Bean
public YamlPropertiesFactoryBean errorPropertiesFromYamlFile() {
final YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
yaml.setResources(new ClassPathResource("errorMessages.yml"));
return yaml;
}
}
I have a web-app-module maven module, which has the previous config-module as a dependency, and as an imported spring application.
In this main module, I also have a configuration class which loads new properties:
@Configuration
public class WebPropertiesConfig {
@Bean
public YamlPropertiesFactoryBean webPropertiesFromYamlFile() {
final YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
yaml.setResources(new ClassPathResource("webProperties.yml"));
return yaml;
}
}
And in this module I also have a class like this:
@Component
@ConfigurationProperties(prefix = "webpart")
public class ConfigPropertiesMapper {
@PostConstruct
public void init() {
//do something here
}
}
And I don't know where it comes from, but the actual order of initialization is this (I checked it within debug mode):
PropertiesConfig.errorPropertiesFromYamlFile() bean creation from
config-module ConfigPropertiesMapper.init() PostConstruct initialization from
web-app-moduleWebPropertiesConfig.webPropertiesFromYamlFile() bean creation from
web-app-moduleWhy is that? And how could I set the order to this?:
PropertiesConfig.errorPropertiesFromYamlFile()WebPropertiesConfig.webPropertiesFromYamlFile()ConfigPropertiesMapper.init()I tried with the @Order, @Qualifier, @Primary annotations, but I could not solve this.
I know one more annotation: @DependsOn. But honestly, I don't want to use it, because then I need to add this annotation to every methods which has @PostConstruct on it.
From the API documentation
"While such order values may influence priorities at injection points, please be aware that they do not influence singleton startup order which is an orthogonal concern determined by dependency relationships and @DependsOn declarations (influencing a runtime-determined dependency graph)."
You need to either a @DependsOn annotation to control creation order.
Or else call all the init methods in one bean so you can control the order. If you inject the other beans you will be sure they have finished creation.
Something like:
@Component
public class InitBean {
@Autowired
privaPropertiesConfig propertiesConfig;
@Autowired
private WebPropertiesConfig webPropertiesConfig;
@Autowired
private ConfigPropertiesMapper configPropertiesMapper;
@PostConstruct
public void init() {
propertiesConfig.errorPropertiesFromYamlFile()
webPropertiesConfig.webPropertiesFromYamlFile()
configPropertiesMapper.init()
}
}
However you should probably add all your properties into one class, spring will find what it can, ignore what it can't and any values duplicate values in errroMessages will be overriden by webProperties.
@Component
@PropertySource(value={ "classpath:errorMessages.yml", "classpath:webProperties.yml"}, ignoreResourceNotFound="true))
@ConfigurationProperties(prefix = "webpart")
public class ConfigPropertiesMapper {
...
}
There are different mechanisms of bean initialization (not bean creation) in Spring/Boot. They can be used regardless of bean dependencies, if desired.
The order (mid. 2020 with Spring Boot 2.3.2) is:
@PostConstruct or InitializingBeanSmartInitializingSingletonsSmartLifecycle beansApplicationStartedEvent is triggeredApplicationReadyEvent is triggered(there are other events too, of course)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With