Spring boot 使用属性文件中的配置创建未知数量的bean

Spring boot 使用属性文件中的配置创建未知数量的bean,spring-boot,properties-file,Spring Boot,Properties File,我的情况是,我有一个属性文件来配置未知数量的bean: 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 : 我有一个配置类来读取这些属性: @Configuration @EnableConfigurationPropertie

我的情况是,我有一个属性文件来配置未知数量的bean:

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
:
我有一个配置类来读取这些属性:

@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() {

  }
}
但是,Spring尝试将参数自动关联到这些方法,而不是使用我在
postConstruct()
中提供的参数

  • BeanFactoryPostProcessor
    BeanDefinitionRegistryPostProcessor
    。但是,在这里,我无法从上面访问属性文件或
    RssConfig
    -bean,因为它在生命周期中调用得太早了


  • 我需要做什么来生成这些动态数量的bean?我可能就在一小步之外。。。与XML解决方案相比,我更喜欢Java配置解决方案。

    您需要注册bean定义(而不是调用
    @bean
    方法),因此
    BeanDefinitionRegistryPostProcessor
    ImportBeanDefinitionRegistrator
    是目前最好的方法。您可以抓取属性文件并使用
    PropertiesConfigurationFactory
    (在Spring Boot中)绑定到它,而不是使用
    @ConfigurationProperties
    ,或者您可以使用父上下文或独立的
    SpringApplication
    在bean定义注册代码中创建并绑定
    RssConfig

    哇,主管回答了我的问题:)是的,我让它与
    属性配置工厂
    BeanDefinitionRegistryPostProcessor
    一起工作。困难的部分是扫描名称空间处理程序的源代码以手动设置这些内容。如果有人读到这篇文章,我建议创建一个典型的XML设置,然后查看bean注册表,了解所有重要的bean是什么样子的。嗨,Dave,2020年有更好的方法吗?你仍然需要提取属性并创建bean。现在有了功能bean注册API(在
    GenericApplicationContext
    中),所以我想这是一个新选项。相关:
      @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));
        }
      }