Creating Unknown Number of Beans With Configuration From Properties-Files

人走茶凉 提交于 2019-12-12 20:30:33

问题


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

  1. 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().

  2. 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.


回答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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!