问题
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 frompostConstruct()
@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 aBeanDefinitionRegistryPostProcessor
. However, here I don't have access to the properties-file or theRssConfig
-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.
回答1:
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.
来源:https://stackoverflow.com/questions/23922318/creating-unknown-number-of-beans-with-configuration-from-properties-files