BeanFactoryPostProcessor
s are a very special kind of concept in Spring. They are components that operate on BeanDefinition
instances, which are a metamodel of the bean instances to be created.
That means, that at the point in time when the BFPP
s are invoked, no bean instances have been created yet as the metamodel is about to be post processed (as the name suggests). Hence beans depended on by the BFPP
will be initialized extremely early in the lifecycle of the container. Thus it's highly recommended to not depend on application components from BFPP
s or - if really required - only on beans that don't necessarily trigger the creation of a lot of downstream components.
That said, you shouldn't depend on especially repositories from BFPP
s as they usually require the creation of a lot of infrastructure components. I'd recommend getting the configuration properties that are required to connect to the configuration database (JDBC URL, username, password, etc.) and just create a throw-away DataSource
that's only used to create a new BeanDefinition
for a new DataSource
that's going to be used by the application eventually.
So here are the recommended steps (from the top of my head - might need some tweaking):
- drop the autowiring of a
DataSource
- configure an
@PropertySource
pointing to the properties containing the coordinates to connect
inject the values of that PropertySource
into the constructor of the BFPP
:
class YourBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public YourBeanFactoryPostProcessor(@Value("#{properties.url}) String url, …) {
// assign to fields
}
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 1. Create throw-away DataSource
// 2. Create JdbcTemplate
// 3. Use template to lookup configuration properties
// 4. Create BeanDefinition for DataSource using properties just read
// 5. Register BeanDefinition with the BeanFactory
}
}