Creating Unknown Number of Beans With Configuration From Properties-Files
properties-file, spring-boot
Solution
You need to register the bean definitions (not call `@Bean` methods), so `BeanDefinitionRegistryPostProcessor` or `ImportBeanDefinitionRegistrar` are the best ways to do that currently. You can grab the properties file and bind to it using `PropertiesConfigurationFactory` (in Spring Boot) instead of using `@ConfigurationProperties`, or maybe you could use a parent context or a standalone `SpringApplication` to create and bind your `RssConfig` inside your bean definition registration code.
Problem
My situation is that I have a properties-file to configure an unknown number of beans: ``` rssfeed.source[0]=http://feed.com/rss-news.xml rssfeed.title[0]=Sample feed #1 rssfeed.source[1]=http://feed.com/rss-news2.xml rssfeed.title[1]=Sample feed #2 : ``` I have a configuration class to read those properties: ``` @Configuration @EnableConfigurationProperties @ConfigurationProperties(prefix = "rssfeed", locations = "classpath:/config/rssfeed.properties") public class RssConfig { private List<String> source = new ArrayList<String>(); private List<String> title = new ArrayList<String>(); public List<String> getSource() { return source; } public List<String> getTitle() { return title; } @PostConstruct public void postConstruct() { } } ``` This is working nicely. However, now I want to create beans based on that. What I've tried so far is add `@Bean`-methods and call them from `postConstruct()` ``` @Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public SourcePollingChannelAdapter createFeedChannelAdapter(int id, String url) { SourcePollingChannelAdapter channelAdapter = new SourcePollingChannelAdapter(); channelAdapter.setApplicationContext(applicationContext); channelAdapter.setBeanName("feedChannelAdapter" + id); channelAdapter.setSource(createMessageSource(id, url)); return channelAdapter; } @Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public FeedEntryMessageSource createMessageSource(int id, String url) { try { FeedEntryMessageSource messageSource = new FeedEntryMessageSource(new URL(url), ""); messageSource.setApplicationContext(applicationContext); messageSource.setBeanName("feedChannelAdapter" + id + ".source"); return messageSource; } catch (Throwable e) { Utility.throwAsUncheckedException(e); return null; } } @Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public QueueChannel createFeedChannel(int id, String url) { QueueChannel channel = new QueueChannel(); channel.setApplicationContext(applicationContext); channel.setBeanName("feedChannel" + id); return channel; } @PostConstruct public void postConstruct() { for (int x = 0; x < source.size(); x++) { createFeedChannelAdapter(x, source.get(x)); } } ``` However, Spring tries to autowire the parameters to those methods rather than using the parameters I provided in `postConstruct()`. a `BeanFactoryPostProcessor` or a `BeanDefinitionRegistryPostProcessor`. However, here I don't have access to the properties-file or the `RssConfig`-bean from above as it's called too early in the lifecycle. What do I need to do generate those dynamic number of beans? I'm probably just a tiny little step away... I prefer a Java configuration-solution over an XML-solution.